-
Notifications
You must be signed in to change notification settings - Fork 0
Consolidate all PR changes into single branch #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…fixes Co-authored-by: danielbodnar <1790726+danielbodnar@users.noreply.github.com>
…, and tests Co-authored-by: danielbodnar <1790726+danielbodnar@users.noreply.github.com>
…dling Co-authored-by: danielbodnar <1790726+danielbodnar@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR consolidates changes from multiple previous PRs (#5, #7, #8, #10) into a single cohesive implementation. It introduces a comprehensive TypeScript-based implementation for the BitBuilder Hypervisor with Effect-TS for functional error handling, runtime schema validation, and systemd integration. The PR also includes critical documentation fixes for systemd network configuration paths.
Changes:
- Documentation fixes: Corrected 11 instances of incorrect systemd network config paths from
/usr/lib/systemd/system/*.networkto/usr/lib/systemd/network/*.networkand improved markdown formatting in STACK.md - TypeScript implementation: Added core type definitions, Effect-TS schema validation, utility functions, network management, template system, tenant operations, service orchestration, and systemd generators
- Testing infrastructure: Comprehensive test suites for schema validation and utility functions using Bun test framework
- Build tooling: Complete development environment with TypeScript, Prettier, oxlint, and Bun runtime configuration
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 26 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.json | TypeScript configuration with strict mode and path aliases for clean imports |
| package.json | Project dependencies and build scripts using Bun runtime and Effect-TS ecosystem |
| .prettierrc.yml, .prettierignore | Code formatting configuration with oxc plugin integration |
| .oxlintrc.json | Linting rules with TypeScript, import, and JSDoc plugin support |
| .gitignore | Added Node.js dependencies and build output exclusions |
| src/types/index.ts | Core TypeScript type definitions for tenants, resources, networking, and system config |
| src/schemas/index.ts | Effect-TS schema definitions with runtime validation for all types |
| src/utils/index.ts | Utility functions for file operations, systemd control, git operations, networking, and logging |
| src/network/index.ts | Network management with bridge creation, interface configuration, and systemd-networkd integration |
| src/templates/index.ts | Template loading, validation, instantiation, and Git-based template cloning |
| src/tenant/index.ts | High-level tenant lifecycle operations including creation, deletion, and provisioning |
| src/services/tenant-manager.ts | Service orchestration with background sync, health monitoring, and graceful shutdown |
| src/generators/tenant-generator.ts | TypeScript orchestrator for systemd unit generation |
| src/generators/tenant-generator | Bash implementation of tenant discovery and unit generation |
| src/generators/mount-generator | Bash generator for overlay mounts, extensions, and tmpfs configurations |
| src/index.ts | Main application entry point with CLI interface |
| test/schemas.test.ts | Comprehensive schema validation tests |
| test/utils.test.ts | Utility function tests covering all major utilities |
| STACK.md | Fixed systemd network configuration paths and markdown formatting |
| Effect.catchAll((error) => { | ||
| logger.warn(`Failed to delete network bridge: ${error}`); | ||
| return Effect.succeed(undefined); | ||
| }) |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logger methods return Effect values but are being called without proper handling. The logger.warn call should be executed with yield* within the Effect context. Simply calling it without handling will not execute the logging.
| Effect.catchAll((error) => { | |
| logger.warn(`Failed to delete network bridge: ${error}`); | |
| return Effect.succeed(undefined); | |
| }) | |
| Effect.catchAll((error) => | |
| Effect.zipRight( | |
| logger.warn(`Failed to delete network bridge: ${error}`), | |
| Effect.succeed(undefined) | |
| ) | |
| ) |
| Effect.catchAll((error) => { | ||
| this.logger.warn(`Git sync failed for tenant ${tenantId}: ${error}`); | ||
| return Effect.succeed(undefined); | ||
| }) |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logger methods return Effect values but are being called without proper handling in the catchAll handlers. Lines 264, 272, 280, and 364 use logger.warn(...) or this.logger.warn(...) without executing the Effect. These should be handled with yield* or using the pipe pattern with Effect.map.
| Effect.catchAll((error) => { | |
| this.logger.warn(`Git sync failed for tenant ${tenantId}: ${error}`); | |
| return Effect.succeed(undefined); | |
| }) | |
| Effect.catchAll((error) => | |
| pipe( | |
| this.logger.warn(`Git sync failed for tenant ${tenantId}: ${error}`), | |
| Effect.map(() => undefined) | |
| ) | |
| ) |
| Schema.pattern(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/) | ||
| ), | ||
| gateway: Schema.optional( | ||
| Schema.String.pipe( | ||
| Schema.pattern(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) | ||
| ) | ||
| ), | ||
| dns: Schema.optional( | ||
| Schema.Array( | ||
| Schema.String.pipe( | ||
| Schema.pattern(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IP address regex patterns on lines 72, 76, 82 allow invalid IP addresses. For example, "999.999.999.999" would match the pattern. Consider using a more precise regex that validates each octet is 0-255, or adding additional validation after the regex match.
| ), | ||
| ipv4: Schema.Union( | ||
| Schema.Literal('dhcp'), | ||
| Schema.Literal('static'), |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "static" literal value on line 69 is included in the union but never actually validated against a specific structure. If ipv4 is set to the string "static", the schema will accept it, but there's no clear indication what this means versus providing the object structure. Consider either removing this literal or adding documentation about when to use "static" versus the object form.
| Schema.Literal('static'), |
| // Remove dangerous path components | ||
| return NodePath.normalize(path).replace(/\.\./g, ''); |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path sanitization on line 353 removes all occurrences of ".." which could corrupt legitimate paths containing ".." in filenames. For example, a file named "test..config" would become "testconfig". Consider using NodePath.resolve() to properly normalize paths while preventing directory traversal, or implement more precise validation.
| // Remove dangerous path components | |
| return NodePath.normalize(path).replace(/\.\./g, ''); | |
| // Normalize and validate path to prevent directory traversal without corrupting filenames | |
| const normalized = NodePath.normalize(path); | |
| const segments = normalized.split(NodePath.sep); | |
| if (segments.includes('..')) { | |
| throw new Error(`Invalid path: directory traversal is not allowed (${path})`); | |
| } | |
| return normalized; |
| import { | ||
| createLogger, | ||
| ensureDirectory, | ||
| pathExists, | ||
| gitClone, | ||
| gitPull, | ||
| getGitCommitHash, | ||
| systemctl, | ||
| daemonReload, | ||
| enableService, | ||
| startService, | ||
| stopService, | ||
| isServiceActive, | ||
| gracefulShutdown, | ||
| GitError, | ||
| SystemdError, | ||
| } from '#utils/index'; |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused imports GitError, SystemdError, gitClone.
| import type { TenantMetadata, TenantStatus } from '#types/index'; | ||
| import { Schema } from '@effect/schema'; | ||
|
|
||
| const logger = createLogger('tenant-manager'); |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable logger.
| * Provides high-level tenant lifecycle operations | ||
| */ | ||
|
|
||
| import { Effect, pipe } from 'effect'; |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import pipe.
| import { Effect, pipe } from 'effect'; | |
| import { Effect } from 'effect'; |
| */ | ||
|
|
||
| import { describe, it, expect } from 'bun:test'; | ||
| import { Effect, Schema } from 'effect'; |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused imports Effect, Schema.
| import { Effect, Schema } from 'effect'; |
| RestartSec=${restart_sec} | ||
| Restart=${restart_policy} |
Copilot
AI
Jan 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Values taken from tenant_json (.metadata.description, .config.restart_policy, and .config.restart_sec) are written directly into the systemd unit (Description=, RestartSec=, and Restart=) without any sanitization or escaping. If an attacker can control these fields in the tenant registry (for example via Git-synced metadata or an API), they can inject newline characters to smuggle additional directives like ExecStart= into the [Service] section and execute arbitrary commands as root when the tenant service starts. To prevent this, constrain these fields to a strict, validated set of safe values (e.g., whitelist restart policies, numeric-only restart intervals, description without control characters) and/or escape or reject newlines and other control characters before rendering them into unit files.
| RestartSec=${restart_sec} | |
| Restart=${restart_policy} | |
| RestartSec=${restart_sec//[^0-9]/} | |
| Restart=${restart_policy//[$'\n'$'\r']/} |
Consolidates changes from PRs #5, #7, #8, and #10 into a single branch with clean commit history.
Documentation Fixes (PRs #8, #10)
/usr/lib/systemd/system/*.network→/usr/lib/systemd/network/*.network(11 occurrences in STACK.md)TypeScript Implementation (PR #5)
Code Review Fixes
catchAllhandlersgenerateSubnetInfohelper to reduce IP calculation duplicationupdateTenantStateCodeQL analysis: no security alerts.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.