Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,22 @@ CI and local verification.

## Production checkout and PR worktrees

`/home/ubuntu/projects/mira-dashboard` is the production checkout. Keep it on `main`; the running service and deploy workflow build from this path only after Raymond approves a merge/deploy.
`/home/ubuntu/projects/mira-dashboard/production/checkout` is the clean production control checkout. Keep it on `main`; after Raymond approves a merge/deploy, the deploy workflow updates this source and builds the exact commit in an isolated detached worktree. Production never builds in or executes from the control checkout.

Feature and autopilot work must use separate git worktrees under `/home/ubuntu/projects/mira-dashboard-worktrees`, for example:
Feature and autopilot work must use separate git worktrees under `/home/ubuntu/projects/mira-dashboard/development/worktrees`, for example:

```bash
mkdir -p /home/ubuntu/projects/mira-dashboard-worktrees
git -C /home/ubuntu/projects/mira-dashboard fetch --prune origin
git -C /home/ubuntu/projects/mira-dashboard worktree add \
mkdir -p /home/ubuntu/projects/mira-dashboard/development/worktrees
git -C /home/ubuntu/projects/mira-dashboard/production/checkout fetch --prune origin
git -C /home/ubuntu/projects/mira-dashboard/production/checkout worktree add \
-b mira/<short-slug> \
/home/ubuntu/projects/mira-dashboard-worktrees/<short-slug> \
/home/ubuntu/projects/mira-dashboard/development/worktrees/<short-slug> \
main
```

Run lint/build verification inside the worktree, not the production checkout. This prevents unapproved PR branches from writing live `dist/` or `backend/dist` artifacts.

The Dashboard PR approval/rejection endpoints attempt to remove the matching local worktree after a PR is merged or rejected. Cleanup is best-effort: it only removes paths under `/home/ubuntu/projects/mira-dashboard-worktrees` and skips worktrees with uncommitted changes.
The Dashboard PR approval/rejection endpoints attempt to remove the matching local worktree after a PR is merged or rejected. Cleanup is best-effort: it only removes paths under `/home/ubuntu/projects/mira-dashboard/development/worktrees` and skips worktrees with uncommitted changes.

## Safety notes for agents

Expand Down
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"build:backend": "bun node_modules/@typescript/native/bin/tsc --noEmit && bun scripts/build.ts",
"db:preflight": "bun dist/databasePreflight.js",
"deploy:prepare:backend": "bun run build:backend && bun run db:preflight",
"auth:reset-password": "MIRA_DASHBOARD_DB_PATH=${MIRA_DASHBOARD_DB_PATH:-/home/ubuntu/projects/mira-dashboard-state/mira-dashboard.db} NODE_ENV=production doppler run --config prd --project rajohan --preserve-env=MIRA_DASHBOARD_DB_PATH -- bun dist/resetDashboardPassword.js",
"auth:reset-password": "NODE_ENV=production doppler run --config prd --project rajohan --preserve-env=NODE_ENV,MIRA_DASHBOARD_PROJECT_ROOT -- bun dist/resetDashboardPassword.js",
"start:backend": "NODE_ENV=production doppler run --config prd --project rajohan -- bun dist/serverStart.js",
"start:worker": "NODE_ENV=production doppler run --config prd --project rajohan -- bun dist/workerStart.js",
"lint:backend": "eslint . --cache --cache-strategy content",
Expand Down
10 changes: 9 additions & 1 deletion backend/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import {
prepareDatabaseStorage,
secureSqliteFilePermissions,
} from "./databaseStorage.ts";
import {
resolveDashboardProjectPathsForRuntime,
resolveDashboardRuntimePath,
} from "./lib/dashboardPaths.ts";

type DatabaseSync = Database;

Expand All @@ -25,7 +29,11 @@ function resolveDatabasePath(): {
configuredDatabasePath: string | undefined;
databasePath: string;
} {
const configuredDatabasePath = process.env.MIRA_DASHBOARD_DB_PATH?.trim();
const projectPaths = resolveDashboardProjectPathsForRuntime();
const configuredDatabasePath = resolveDashboardRuntimePath(
projectPaths?.productionDatabasePath,
process.env.MIRA_DASHBOARD_DB_PATH
);
return {
configuredDatabasePath,
databasePath: configuredDatabasePath
Expand Down
13 changes: 13 additions & 0 deletions backend/src/databaseMigrations/0007DeploymentRetentionIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { DatabaseMigration } from "./types.ts";

export const deploymentRetentionIndexMigration: DatabaseMigration = {
version: 7,
Comment thread
rajohan marked this conversation as resolved.
name: "deployment-retention-index",
sql: `
DROP INDEX IF EXISTS idx_deployment_jobs_retention;

CREATE INDEX idx_deployment_jobs_retention
ON deployment_jobs(started_at DESC, id DESC, status)
WHERE status NOT IN ('building', 'verifying');
`,
};
2 changes: 2 additions & 0 deletions backend/src/databaseMigrations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { sessionValidatorHashMigration } from "./0003SessionValidatorHash.ts";
import { maintenanceCoverageMigration } from "./0004MaintenanceCoverage.ts";
import { auditEventsMigration } from "./0005AuditEvents.ts";
import { multiFactorAuthenticationMigration } from "./0006MultiFactorAuthentication.ts";
import { deploymentRetentionIndexMigration } from "./0007DeploymentRetentionIndex.ts";
import type { DatabaseMigration } from "./types.ts";

export const databaseMigrations: readonly DatabaseMigration[] = [
Expand All @@ -13,6 +14,7 @@ export const databaseMigrations: readonly DatabaseMigration[] = [
maintenanceCoverageMigration,
auditEventsMigration,
multiFactorAuthenticationMigration,
deploymentRetentionIndexMigration,
];

export interface DatabaseMigrationIdentity {
Expand Down
9 changes: 5 additions & 4 deletions backend/src/databaseSchemaCompatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import { databaseMigrations } from "./databaseMigrations/index.ts";
const CURRENT_DATABASE_SCHEMA_VERSION = databaseMigrations.at(-1)?.version ?? 0;

/**
* Keep this range explicit. An expand migration may widen the maximum before
* the migration ships; a contract migration must narrow it only after the
* previous release has left the rollback window.
* Runtime schema versions this release can safely open. This is not a promise
* that migrations are reversible: failed coordinated cutovers restore their
* pre-cutover snapshot before older code starts, while later manual rollbacks
* remain bounded by the live schema.
*/
export const DASHBOARD_DATABASE_SCHEMA_COMPATIBILITY = Object.freeze({
maximum: 6,
maximum: 7,
Comment thread
rajohan marked this conversation as resolved.
minimum: 6,
target: CURRENT_DATABASE_SCHEMA_VERSION,
});
Expand Down
Loading