fix: resume distributed task ID counter past existing IDs; extract plugin view types
The dashboard task-create route now uses the distributed task ID allocator (FN-3450). On projects whose tasks had been allocated through the legacy config.nextId counter, the allocator's `ensureStateRow` was seeding a fresh prefix at sequence 1, so new tasks restarted at FN-001 even when FN-3700 already existed. ensureStateRow now seeds past: - the legacy config.nextId counter (when configured taskPrefix matches), and - one past the highest numeric suffix on any existing tasks/archivedTasks row for the prefix. A regression test seeds FN-3700 in a fresh DB and asserts the next reservation returns FN-3701, not FN-001. Plugin dashboard view contracts are now exposed via a slim type-only module (`@fusion/dashboard/app/plugins/types`). External plugin tsc builds previously imported `pluginViewRegistry`, transitively pulling in dashboard runtime sources (React components, CSS, lucide-react). The dependency-graph plugin's import + path mapping is updated to use the new module. Schema housekeeping: drop unused scaffolding tables left over from an earlier migration via a new idempotent migration (v67). Fresh DBs see no change; existing DBs that ran the older migration get the orphan tables dropped on next init. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -88,7 +88,7 @@ export function probeFts5(db: DatabaseSync): boolean {
|
||||
|
||||
// ── Schema Definition ────────────────────────────────────────────────
|
||||
|
||||
const SCHEMA_VERSION = 66;
|
||||
const SCHEMA_VERSION = 67;
|
||||
|
||||
function normalizeTaskComments(
|
||||
steeringComments: SteeringComment[] | undefined,
|
||||
@@ -825,59 +825,6 @@ CREATE TABLE IF NOT EXISTS todo_items (
|
||||
CREATE INDEX IF NOT EXISTS idxTodoListsProjectId ON todo_lists(projectId);
|
||||
CREATE INDEX IF NOT EXISTS idxTodoItemsListId ON todo_items(listId);
|
||||
CREATE INDEX IF NOT EXISTS idxTodoItemsSortOrder ON todo_items(listId, sortOrder);
|
||||
|
||||
-- Project-scoped auth domain tables (FN-3515)
|
||||
CREATE TABLE IF NOT EXISTS project_auth_users (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT NOT NULL,
|
||||
displayName TEXT,
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_auth_memberships (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_auth_providers (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
providerUserId TEXT NOT NULL,
|
||||
metadata TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE,
|
||||
UNIQUE(provider, providerUserId)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_auth_sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
membershipId TEXT NOT NULL,
|
||||
sessionToken TEXT NOT NULL UNIQUE,
|
||||
expiresAt TEXT NOT NULL,
|
||||
revokedAt TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (membershipId) REFERENCES project_auth_memberships(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthUsersEmail ON project_auth_users(email);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthMembershipsUserId ON project_auth_memberships(userId);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthMembershipsRole ON project_auth_memberships(role);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthProvidersUserId ON project_auth_providers(userId);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsUserId ON project_auth_sessions(userId);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsMembershipId ON project_auth_sessions(membershipId);
|
||||
CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsExpiry ON project_auth_sessions(expiresAt);
|
||||
`;
|
||||
|
||||
// ── Database Class ───────────────────────────────────────────────────
|
||||
@@ -2674,66 +2621,6 @@ export class Database {
|
||||
});
|
||||
}
|
||||
|
||||
if (version < 63) {
|
||||
this.applyMigration(63, () => {
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS project_auth_users (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT NOT NULL,
|
||||
displayName TEXT,
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL
|
||||
)
|
||||
`);
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS project_auth_memberships (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
role TEXT NOT NULL,
|
||||
active INTEGER NOT NULL DEFAULT 1,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS project_auth_providers (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
providerUserId TEXT NOT NULL,
|
||||
metadata TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE,
|
||||
UNIQUE(provider, providerUserId)
|
||||
)
|
||||
`);
|
||||
this.db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS project_auth_sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
userId TEXT NOT NULL,
|
||||
membershipId TEXT NOT NULL,
|
||||
sessionToken TEXT NOT NULL UNIQUE,
|
||||
expiresAt TEXT NOT NULL,
|
||||
revokedAt TEXT,
|
||||
createdAt TEXT NOT NULL,
|
||||
updatedAt TEXT NOT NULL,
|
||||
FOREIGN KEY (userId) REFERENCES project_auth_users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (membershipId) REFERENCES project_auth_memberships(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthUsersEmail ON project_auth_users(email)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthMembershipsUserId ON project_auth_memberships(userId)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthMembershipsRole ON project_auth_memberships(role)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthProvidersUserId ON project_auth_providers(userId)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsUserId ON project_auth_sessions(userId)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsMembershipId ON project_auth_sessions(membershipId)`);
|
||||
this.db.exec(`CREATE INDEX IF NOT EXISTS idxProjectAuthSessionsExpiry ON project_auth_sessions(expiresAt)`);
|
||||
});
|
||||
}
|
||||
|
||||
if (version < 64) {
|
||||
this.applyMigration(64, () => {
|
||||
this.db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idxEvalTaskResultsRunTaskUnique ON eval_task_results(runId, taskId)`);
|
||||
@@ -2782,6 +2669,20 @@ export class Database {
|
||||
});
|
||||
}
|
||||
|
||||
if (version < 67) {
|
||||
// Drop the project_auth_* tables introduced by the old migration 63
|
||||
// (FN-3544). The pluggable project-auth feature was removed before any
|
||||
// production usage; these tables are orphaned on DBs that ran the old
|
||||
// migration. Drop sessions/providers/memberships before users so the
|
||||
// foreign-key cascade order is honored.
|
||||
this.applyMigration(67, () => {
|
||||
this.db.exec(`DROP TABLE IF EXISTS project_auth_sessions`);
|
||||
this.db.exec(`DROP TABLE IF EXISTS project_auth_providers`);
|
||||
this.db.exec(`DROP TABLE IF EXISTS project_auth_memberships`);
|
||||
this.db.exec(`DROP TABLE IF EXISTS project_auth_users`);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user