feat(FN-5411): add project identity recovery and identity-aware startup rea
Implements project identity tracking and recovery across the Fusion system (FN-5411), enabling persistent identity for projects across storage migrations, daemon reattaches, and CLI session management. Adds a project identity metadata API and central reattach ensure mechanism, wires identity stampin Fusion-Task-Id: FN-5411 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> Fusion-Task-Id: FN-5411
This commit is contained in:
@@ -61,6 +61,18 @@ If one side succeeds and the other fails, the next scheduler/self-healing tick r
|
||||
|
||||
This fencing prevents double-claims: a restarted or delayed stale owner cannot reclaim work once central ownership has been released and lease generation has advanced.
|
||||
|
||||
## Recovering after a central DB wipe
|
||||
|
||||
If a project's row is deleted from `~/.fusion/fusion-central.db`, Fusion now automatically recovers on next startup:
|
||||
|
||||
1. Startup checks central for a row at the project path.
|
||||
2. If missing, it reads `__meta.projectIdentity` from `<project>/.fusion/fusion.db`.
|
||||
3. If present, central reattaches that exact `projectId` instead of creating a new one.
|
||||
|
||||
This prevents “empty workspace” regressions where project data still exists locally but is keyed to an older `projectId`.
|
||||
|
||||
Backups remain the first-line protection strategy (see FN-5407), but this identity reattach path lets operators recover even when no central backup is available.
|
||||
|
||||
## Registering and Managing Projects
|
||||
|
||||
```bash
|
||||
@@ -331,3 +343,11 @@ flowchart TD
|
||||
```
|
||||
|
||||
See also: [Architecture](./architecture.md), [CLI Reference](./cli-reference.md), and [Missions](./missions.md).
|
||||
|
||||
## Identity persistence and recovery
|
||||
|
||||
Each project persists its canonical central identity inside `.fusion/fusion.db` `__meta` as `projectId` and `projectCreatedAt`. Registration paths should use `CentralCore.ensureProjectForPath({ path, identity, ... })` after reading local identity with `readProjectIdentity()`; this reattaches central rows when central was wiped and refuses silent remint if the persisted id is owned by another path.
|
||||
|
||||
Dashboard `POST /api/projects` now surfaces this mismatch as `409` with `error: "orphan-identity"` and recovery metadata, and callers can opt into recovery flows with `acceptRecovery: true` behavior at the route layer.
|
||||
|
||||
Central DB backup coverage is already enabled by default (`BackupManager` uses `includeCentralDb: true`), so identity recovery data remains in the normal daily backup set.
|
||||
|
||||
@@ -339,7 +339,7 @@ The `tasks.githubTracking` JSON column stores per-task GitHub tracking state (`e
|
||||
| `secrets` | Encrypted secret KV rows (`key` unique) with raw BLOB `value_ciphertext` + per-row random `nonce` (AES-256-GCM), per-secret `access_policy` CHECK (`auto`/`prompt`/`deny`), env-materialization metadata (`env_exportable`, `env_export_key`), and read-audit fields (`last_read_at`, `last_read_by`). Plaintext is never written to the database. |
|
||||
| `task_documents` | Task-scoped document metadata/content keyed by `(taskId, key)` with current revision pointer. |
|
||||
| `task_document_revisions` | Immutable revision history for task documents (content snapshots by revision). |
|
||||
| `__meta` | Schema version + monotonic `lastModified` change detector, plus one-time bootstrap metadata such as `bootstrappedAt`. |
|
||||
| `__meta` | Schema version + monotonic `lastModified` change detector, plus one-time bootstrap metadata such as `bootstrappedAt` and `projectIdentity`. |
|
||||
| `missions` | Mission-level planning hierarchy root. |
|
||||
| `milestones` | Milestones under missions, including dependency lists and validation state. |
|
||||
| `slices` | Slices under milestones with plan-state/activation metadata. |
|
||||
@@ -393,6 +393,16 @@ The `tasks.githubTracking` JSON column stores per-task GitHub tracking state (`e
|
||||
|
||||
Invariant: after init, every declared column for covered tables exists regardless of `__meta.schemaVersion` whenever the fingerprint is stale or missing, preventing legacy drift from causing `no such column` regressions on newly added fields while keeping unchanged-schema opens fast.
|
||||
|
||||
### Project identity row (`__meta.projectIdentity`)
|
||||
|
||||
Each project-scoped `.fusion/fusion.db` now stores the canonical central registry identity in `__meta.projectIdentity` as JSON:
|
||||
|
||||
```json
|
||||
{ "id": "proj_0123456789abcdef", "createdAt": "2026-05-21T12:00:00.000Z", "firstSeenPath": "/abs/project/path" }
|
||||
```
|
||||
|
||||
This is written on first successful registration (and back-filled on later startup for older projects). If `~/.fusion/fusion-central.db` loses the row for that path, startup reads this identity and reattaches the same `projectId` instead of minting a new id. That preserves project-scoped rows keyed by `projectId` (`todo_lists`, `chat_sessions`, `project_insights`, etc.).
|
||||
|
||||
---
|
||||
|
||||
### Chat rooms (migration 70)
|
||||
|
||||
Reference in New Issue
Block a user