@stigmer/server 3.19.0 → 3.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/authorization/model/index.d.ts +1 -1
  2. package/dist/authorization/model/index.d.ts.map +1 -1
  3. package/dist/authorization/model/index.js +0 -2
  4. package/dist/authorization/model/index.js.map +1 -1
  5. package/dist/authorization/model/organization.d.ts.map +1 -1
  6. package/dist/authorization/model/organization.js +0 -1
  7. package/dist/authorization/model/organization.js.map +1 -1
  8. package/dist/boot/compose.d.ts.map +1 -1
  9. package/dist/boot/compose.js +2 -15
  10. package/dist/boot/compose.js.map +1 -1
  11. package/dist/boot/inprocess.d.ts +2 -13
  12. package/dist/boot/inprocess.d.ts.map +1 -1
  13. package/dist/boot/inprocess.js +6 -16
  14. package/dist/boot/inprocess.js.map +1 -1
  15. package/dist/domain/workflow/registry/data/task-kind-registry.json +0 -1
  16. package/dist/pipeline/interceptors/auth.d.ts +1 -1
  17. package/dist/pipeline/interceptors/auth.js +1 -1
  18. package/dist/query/search/registry.d.ts +3 -5
  19. package/dist/query/search/registry.d.ts.map +1 -1
  20. package/dist/query/search/registry.js +3 -7
  21. package/dist/query/search/registry.js.map +1 -1
  22. package/dist/store/postgres/migrations.d.ts +3 -1
  23. package/dist/store/postgres/migrations.d.ts.map +1 -1
  24. package/dist/store/postgres/migrations.js +19 -1
  25. package/dist/store/postgres/migrations.js.map +1 -1
  26. package/dist/store/sqlite/migrations.d.ts +3 -1
  27. package/dist/store/sqlite/migrations.d.ts.map +1 -1
  28. package/dist/store/sqlite/migrations.js +22 -1
  29. package/dist/store/sqlite/migrations.js.map +1 -1
  30. package/package.json +6 -6
  31. package/src/authorization/__tests__/derived-tuples.test.ts +1 -1
  32. package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +6 -6
  33. package/src/authorization/__tests__/wire-permissions.test.ts +0 -1
  34. package/src/authorization/model/__tests__/registry.test.ts +0 -9
  35. package/src/authorization/model/index.ts +1 -3
  36. package/src/authorization/model/organization.ts +0 -1
  37. package/src/boot/compose.ts +2 -15
  38. package/src/boot/inprocess.ts +8 -29
  39. package/src/domain/iampolicy/__tests__/role-lifecycle.test.ts +0 -1
  40. package/src/domain/workflow/registry/data/task-kind-registry.json +0 -1
  41. package/src/pipeline/__tests__/router-transport.test.ts +1 -1
  42. package/src/pipeline/interceptors/auth.ts +1 -1
  43. package/src/query/__tests__/query-services.test.ts +16 -18
  44. package/src/query/search/__tests__/criteria.test.ts +3 -6
  45. package/src/query/search/__tests__/query-store.test.ts +21 -21
  46. package/src/query/search/registry.ts +3 -7
  47. package/src/store/postgres/__tests__/migrations.test.ts +23 -4
  48. package/src/store/postgres/migrations.ts +20 -1
  49. package/src/store/sqlite/__tests__/migrations.test.ts +26 -2
  50. package/src/store/sqlite/migrations.ts +23 -1
  51. package/dist/authorization/model/project.d.ts +0 -2
  52. package/dist/authorization/model/project.d.ts.map +0 -1
  53. package/dist/authorization/model/project.js +0 -32
  54. package/dist/authorization/model/project.js.map +0 -1
  55. package/dist/domain/project/controller.d.ts +0 -48
  56. package/dist/domain/project/controller.d.ts.map +0 -1
  57. package/dist/domain/project/controller.js +0 -192
  58. package/dist/domain/project/controller.js.map +0 -1
  59. package/dist/domain/project/reconcile.d.ts +0 -77
  60. package/dist/domain/project/reconcile.d.ts.map +0 -1
  61. package/dist/domain/project/reconcile.js +0 -179
  62. package/dist/domain/project/reconcile.js.map +0 -1
  63. package/dist/domain/project/search-extractor.d.ts +0 -3
  64. package/dist/domain/project/search-extractor.d.ts.map +0 -1
  65. package/dist/domain/project/search-extractor.js +0 -43
  66. package/dist/domain/project/search-extractor.js.map +0 -1
  67. package/src/authorization/model/project.ts +0 -47
  68. package/src/domain/project/__tests__/project.composed.test.ts +0 -381
  69. package/src/domain/project/__tests__/reconcile.test.ts +0 -447
  70. package/src/domain/project/controller.ts +0 -387
  71. package/src/domain/project/reconcile.ts +0 -296
  72. package/src/domain/project/search-extractor.ts +0 -71
@@ -12,11 +12,9 @@
12
12
  * (registry.go ValidateExpectedKinds; server.go:509): a missing extractor
13
13
  * degrades that kind to unsearchable, never refuses boot.
14
14
  *
15
- * The project extractor is registered here by THIS sub-project (#14)
16
- * although the project DOMAIN ports with #16 — boot RebuildIndex re-indexes
17
- * every registered kind from the resources table, and an adopted Go
18
- * database may already hold projects; without the extractor those rows
19
- * would silently vanish from search (D4 #14 DD-D, owner-ratified).
15
+ * Boot RebuildIndex re-indexes every registered kind from the resources
16
+ * table, so a kind with no extractor here is a kind whose rows vanish from
17
+ * search on the next boot; a domain and its extractor land together.
20
18
  */
21
19
  import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
22
20
 
@@ -28,7 +26,6 @@ import { executionContextSearchExtractor } from "../../domain/executioncontext/s
28
26
  import { mcpServerSearchExtractor } from "../../domain/mcpserver/search-extractor.js";
29
27
  import { organizationSearchExtractor } from "../../domain/organization/search-extractor.js";
30
28
  import { pluginSearchExtractor } from "../../domain/plugin/search-extractor.js";
31
- import { projectSearchExtractor } from "../../domain/project/search-extractor.js";
32
29
  import { sessionSearchExtractor } from "../../domain/session/search-extractor.js";
33
30
  import { skillSearchExtractor } from "../../domain/skill/search-extractor.js";
34
31
  import { workflowSearchExtractor } from "../../domain/workflow/search-extractor.js";
@@ -116,7 +113,6 @@ export function newSearchableResourceRegistry(): SearchableResourceRegistry {
116
113
  mcpServerSearchExtractor,
117
114
  organizationSearchExtractor,
118
115
  pluginSearchExtractor,
119
- projectSearchExtractor,
120
116
  sessionSearchExtractor,
121
117
  skillSearchExtractor,
122
118
  workflowSearchExtractor,
@@ -91,24 +91,43 @@ describe.skipIf(testDatabaseAdminUrl() === undefined)(
91
91
  }
92
92
  });
93
93
 
94
- it("a v1 database resumes the chain on reopen: the v2/v3 indexes arrive", async () => {
94
+ it("a v1 database resumes the chain on reopen: the v2/v3 indexes arrive and v4 removes the Project rows", async () => {
95
95
  const store = await PostgresStore.open(db.databaseUrl);
96
96
  await store.close();
97
97
 
98
- // Rewind to a v1 database: drop exactly what v2+v3 created and their
99
- // version rows — the state any pre-v2 deployment is actually in.
98
+ // Rewind to a v1 database: drop exactly what v2+v4 created and their
99
+ // version rows — the state any pre-v2 deployment is actually in —
100
+ // and seed one row of the Project kind an earlier release wrote
101
+ // (the kind column holds the enum NAME) beside a row v4 must keep.
100
102
  const client = new pg.Client({ connectionString: db.databaseUrl });
101
103
  await client.connect();
102
104
  try {
103
105
  await client.query(`DROP INDEX idx_wfee_created_at`);
104
106
  await client.query(`DROP INDEX idx_oauth_grant_resource`);
105
107
  await client.query(
106
- `DELETE FROM schema_version WHERE version IN (2, 3)`,
108
+ `DELETE FROM schema_version WHERE version IN (2, 3, 4)`,
109
+ );
110
+ await client.query(
111
+ `INSERT INTO resources (kind, id, data) VALUES ('project', 'prj_seeded', '\\x00'), ('organization', 'acme', '\\x00')`,
112
+ );
113
+ await client.query(
114
+ `INSERT INTO resource_audit (kind, resource_id, data, version_hash, tag) VALUES ('project', 'prj_seeded', '\\x00', '', '')`,
107
115
  );
108
116
 
109
117
  const reopened = await PostgresStore.open(db.databaseUrl);
110
118
  await reopened.close();
111
119
 
120
+ const remaining = await client.query(
121
+ `SELECT kind, id FROM resources ORDER BY kind`,
122
+ );
123
+ expect(remaining.rows, "v4 removed the Project row and kept the rest").toEqual([
124
+ { kind: "organization", id: "acme" },
125
+ ]);
126
+ const projectAudit = await client.query(
127
+ `SELECT count(*)::int AS n FROM resource_audit WHERE kind = 'project'`,
128
+ );
129
+ expect((projectAudit.rows[0] as { n: number }).n).toBe(0);
130
+
112
131
  const sweepIndex = await client.query(
113
132
  `SELECT indexname FROM pg_indexes
114
133
  WHERE tablename = 'workflow_execution_events'
@@ -41,9 +41,11 @@ import type { PoolClient } from "pg";
41
41
  export const SCHEMA_VERSION_1 = 1;
42
42
  export const SCHEMA_VERSION_2 = 2;
43
43
  export const SCHEMA_VERSION_3 = 3;
44
+ /** v4: the rows of the removed Project kind deleted. */
45
+ export const SCHEMA_VERSION_4 = 4;
44
46
 
45
47
  /** Target version for new databases. */
46
- export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_3;
48
+ export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_4;
47
49
 
48
50
  /**
49
51
  * Advisory lock key for the migration chain. Arbitrary but stable 64-bit
@@ -76,6 +78,7 @@ export async function runMigrations(client: PoolClient): Promise<void> {
76
78
  [SCHEMA_VERSION_1, migrateToV1],
77
79
  [SCHEMA_VERSION_2, migrateToV2],
78
80
  [SCHEMA_VERSION_3, migrateToV3],
81
+ [SCHEMA_VERSION_4, migrateToV4],
79
82
  ];
80
83
 
81
84
  for (const [version, migrate] of chain) {
@@ -296,3 +299,19 @@ async function migrateToV3(client: PoolClient): Promise<void> {
296
299
  CREATE INDEX idx_oauth_grant_resource ON oauth_grant (resource_id, org_id);
297
300
  `);
298
301
  }
302
+
303
+ /**
304
+ * v4: the Project kind (kind 60, id prefix "prj") was removed from the
305
+ * contract, so a database seeded by an earlier release may hold rows no
306
+ * code can read, list or delete any more. The chain's first data
307
+ * migration, and the same shape as the sqlite driver's v9: rows deleted,
308
+ * not archived (the audit table is the version history of kinds the
309
+ * server serves), keyed on the enum NAME the kind column holds
310
+ * (proto-fields.ts apiResourceKindName), the search index left to boot's
311
+ * RebuildIndex. Member rows the Project once listed are ordinary
312
+ * resources of their own kinds and stay.
313
+ */
314
+ async function migrateToV4(client: PoolClient): Promise<void> {
315
+ await client.query(`DELETE FROM resources WHERE kind = 'project'`);
316
+ await client.query(`DELETE FROM resource_audit WHERE kind = 'project'`);
317
+ }
@@ -81,7 +81,7 @@ describe("fresh database", () => {
81
81
  const rows = db
82
82
  .prepare(`SELECT version FROM schema_version ORDER BY version`)
83
83
  .all() as Array<{ version: number }>;
84
- expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8]);
84
+ expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]);
85
85
  });
86
86
 
87
87
  it("re-opening an already-migrated database is a no-op", async () => {
@@ -106,8 +106,21 @@ describe("Go-created v6 database adoption (DD-002 fixture)", () => {
106
106
  cleanups.push(() => fixture.cleanup());
107
107
 
108
108
  // Preconditions: the fixture really is a v6 database with live data.
109
+ // Beside the fixture's rows, one row of the Project kind an earlier
110
+ // release seeded (the kind column holds the enum NAME): v9 must
111
+ // remove exactly it, from both tables, and nothing else.
109
112
  const before = new DatabaseSync(fixture.dbPath);
110
113
  expect(getSchemaVersion(before)).toBe(6);
114
+ before
115
+ .prepare(
116
+ `INSERT INTO resources (kind, id, data, updated_at) VALUES ('project', 'prj_seeded', X'00', '2026-08-23 11:43:54')`,
117
+ )
118
+ .run();
119
+ before
120
+ .prepare(
121
+ `INSERT INTO resource_audit (kind, resource_id, data, archived_at, version_hash, tag) VALUES ('project', 'prj_seeded', X'00', '2026-08-23 11:43:54', '', '')`,
122
+ )
123
+ .run();
111
124
  before.close();
112
125
 
113
126
  const store = SqliteStore.open(fixture.dbPath);
@@ -125,10 +138,20 @@ describe("Go-created v6 database adoption (DD-002 fixture)", () => {
125
138
  expect(org.id).toBe("acme");
126
139
 
127
140
  const audit = db
128
- .prepare(`SELECT version_hash, tag FROM resource_audit`)
141
+ .prepare(`SELECT version_hash, tag FROM resource_audit WHERE kind = 'organization'`)
129
142
  .get() as { version_hash: string; tag: string };
130
143
  expect(audit).toEqual({ version_hash: "hash-v1", tag: "stable" });
131
144
 
145
+ // v9 removed the Project rows and nothing else.
146
+ const projectRows = db
147
+ .prepare(
148
+ `SELECT (SELECT count(*) FROM resources WHERE kind = 'project') AS resources,
149
+ (SELECT count(*) FROM resource_audit WHERE kind = 'project') AS audit,
150
+ (SELECT count(*) FROM resources) AS total`,
151
+ )
152
+ .get() as { resources: number; audit: number; total: number };
153
+ expect(projectRows).toEqual({ resources: 0, audit: 0, total: 1 });
154
+
132
155
  const bootstrap = db
133
156
  .prepare(
134
157
  `SELECT value FROM bootstrap_state WHERE key = 'seedpack_version'`,
@@ -214,6 +237,7 @@ describe("v7 column reconciliation", () => {
214
237
  CREATE TABLE schema_version (version INTEGER PRIMARY KEY, applied_at TEXT NOT NULL DEFAULT (datetime('now')));
215
238
  INSERT INTO schema_version (version) VALUES (1),(2),(3),(4),(5),(6);
216
239
  CREATE TABLE resources (kind TEXT NOT NULL, id TEXT NOT NULL, data BLOB NOT NULL, updated_at TEXT NOT NULL DEFAULT (datetime('now')), PRIMARY KEY (kind, id)) WITHOUT ROWID;
240
+ CREATE TABLE resource_audit (id INTEGER PRIMARY KEY AUTOINCREMENT, kind TEXT NOT NULL, resource_id TEXT NOT NULL, data BLOB NOT NULL, archived_at TEXT NOT NULL DEFAULT (datetime('now')), version_hash TEXT, tag TEXT);
217
241
  CREATE TABLE pending_oauth_state (
218
242
  state TEXT PRIMARY KEY,
219
243
  code_verifier TEXT NOT NULL,
@@ -42,9 +42,11 @@ export const SCHEMA_VERSION_6 = 6;
42
42
  export const SCHEMA_VERSION_7 = 7;
43
43
  /** v8: the by-resource grant-teardown index (the C3 channel installer). */
44
44
  export const SCHEMA_VERSION_8 = 8;
45
+ /** v9: the rows of the removed Project kind deleted. */
46
+ export const SCHEMA_VERSION_9 = 9;
45
47
 
46
48
  /** Target version for new databases. */
47
- export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_8;
49
+ export const CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_9;
48
50
 
49
51
  /** Applies all pending migrations in order. */
50
52
  export function runMigrations(db: DatabaseSync): void {
@@ -66,6 +68,7 @@ export function runMigrations(db: DatabaseSync): void {
66
68
  [SCHEMA_VERSION_6, migrateToV6],
67
69
  [SCHEMA_VERSION_7, migrateToV7],
68
70
  [SCHEMA_VERSION_8, migrateToV8],
71
+ [SCHEMA_VERSION_9, migrateToV9],
69
72
  ];
70
73
 
71
74
  for (const [version, migrate] of chain) {
@@ -357,3 +360,22 @@ function migrateToV8(db: DatabaseSync): void {
357
360
  CREATE INDEX IF NOT EXISTS idx_oauth_grant_resource ON oauth_grant(resource_id, org_id);
358
361
  `);
359
362
  }
363
+
364
+ /**
365
+ * v9: the Project kind (kind 60, id prefix "prj") was removed from the
366
+ * contract, so a database seeded by an earlier release may hold rows no
367
+ * code can read, list or delete any more. Rows are deleted, not archived:
368
+ * the audit table is the version history of kinds the server serves, and
369
+ * bytes of a kind nothing will ever decode are not history. The kind
370
+ * column holds the enum NAME (proto-fields.ts apiResourceKindName), which
371
+ * is why the literal string works after the enum value is gone. The search
372
+ * index is not touched here: boot's RebuildIndex clears it and re-indexes
373
+ * only the registered kinds. Member rows the Project once listed are
374
+ * ordinary resources of their own kinds and stay.
375
+ */
376
+ function migrateToV9(db: DatabaseSync): void {
377
+ db.exec(`
378
+ DELETE FROM resources WHERE kind = 'project';
379
+ DELETE FROM resource_audit WHERE kind = 'project';
380
+ `);
381
+ }
@@ -1,2 +0,0 @@
1
- export declare const projectDeclaration: import("./rewrite.js").KindDeclaration;
2
- //# sourceMappingURL=project.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/authorization/model/project.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,kBAAkB,wCA2B7B,CAAC"}
@@ -1,32 +0,0 @@
1
- /**
2
- * Transcript of fga/model/tenancy/project.fga — an organization's
3
- * grouping: admins own it, and `viewer from organization` lets every
4
- * organization viewer read it without a visibility tuple (projects have
5
- * no visibility axis in `kind_meta`; the whole organization is their
6
- * audience by the model's own line).
7
- */
8
- import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
9
- import { ProjectSchema } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/api_pb";
10
- import { computed, declareKind, direct, from, objectOf, union, } from "./rewrite.js";
11
- export const projectDeclaration = declareKind({
12
- kind: ApiResourceKind.project,
13
- schema: ProjectSchema,
14
- source: "fga/model/tenancy/project.fga",
15
- relations: [
16
- ["organization", direct(objectOf("organization"))],
17
- [
18
- "owner",
19
- union(direct(objectOf("identity_account")), from("admin", "organization")),
20
- ],
21
- [
22
- "viewer",
23
- union(direct(objectOf("identity_account")), computed("owner"), from("viewer", "organization")),
24
- ],
25
- ["can_view", computed("viewer")],
26
- ["can_edit", computed("owner")],
27
- ["can_delete", computed("owner")],
28
- ["can_grant_access", computed("owner")],
29
- ["can_view_access", computed("viewer")],
30
- ],
31
- });
32
- //# sourceMappingURL=project.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/authorization/model/project.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AACtH,OAAO,EAAE,aAAa,EAAE,MAAM,sDAAsD,CAAC;AAErF,OAAO,EACL,QAAQ,EACR,WAAW,EACX,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;IAC5C,IAAI,EAAE,eAAe,CAAC,OAAO;IAC7B,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,+BAA+B;IACvC,SAAS,EAAE;QACT,CAAC,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QAClD;YACE,OAAO;YACP,KAAK,CACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EACpC,IAAI,CAAC,OAAO,EAAE,cAAc,CAAC,CAC9B;SACF;QACD;YACE,QAAQ;YACR,KAAK,CACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EACpC,QAAQ,CAAC,OAAO,CAAC,EACjB,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,CAC/B;SACF;QACD,CAAC,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC,YAAY,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC,iBAAiB,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;KACxC;CACF,CAAC,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * Project controller — ports pkg/domain/project/controller (command + query
3
- * sides). Project is the aggregate root grouping related resources: its spec
4
- * carries lightweight ApiResourceReference members the CLI derives from
5
- * individual apply responses (never user-authored); apply reconciles the
6
- * membership and prunes orphans through the four downstream domains'
7
- * in-process clients — the widest client fan-out of any CRUD domain, which
8
- * is why it ported last of Class A (D4 #16).
9
- *
10
- * Pipeline per RPC mirrors the Go step chains character-for-character; the
11
- * create/update ASYMMETRY is contract: create runs ValidateVisibility and
12
- * NormalizeReferences, update runs neither (an updated members list persists
13
- * without reference normalization — Go update.go). No chain runs
14
- * ValidateReferences: members referencing nonexistent resources persist
15
- * silently. Delete removes ONLY the project — members are never cascaded.
16
- *
17
- * Proven by project.conformance.test.ts (CONFORMANCE_TARGET=local) and
18
- * __tests__/{reconcile,project.composed}.test.ts (the conformance suite
19
- * never touches spec.members or last_reconciliation; the composed tests own
20
- * those pins).
21
- *
22
- * Versus Stigmer Cloud, OSS excludes the Authorize, CreateIamPolicies,
23
- * Publish, and TransformResponse steps (no multi-tenant auth, IAM/FGA, or
24
- * event publishing here).
25
- */
26
- import type { ConnectRouter } from "@connectrpc/connect";
27
- import type { Logger } from "../../boot/logger.js";
28
- import type { Authorizer } from "../../extensions/authorizer.js";
29
- import type { ResourceAuthorizationLifecycle } from "../../extensions/resource-authorization.js";
30
- import type { Store } from "../../store/interface.js";
31
- import type { OrphanDeleter } from "./reconcile.js";
32
- export interface ProjectControllerDeps {
33
- readonly store: Store;
34
- readonly logger: Logger;
35
- /** The composed authorization seam — the Authorize step at position 1 of every chain calls it (O2, DD-007 §3). */
36
- readonly authorizer: Authorizer;
37
- /** The composed tuple-lifecycle driver — undefined = the shared steps no-op (C2). */
38
- readonly authorizationLifecycle: ResourceAuthorizationLifecycle | undefined;
39
- /**
40
- * The four downstream delete edges (agent/workflow/mcp_server/skill),
41
- * lazy per the compose root's boot-ordering idiom — the TS replacement
42
- * for Go's SetReconciliationService late-bind (server.go:635-648).
43
- */
44
- readonly orphanDeleter: () => OrphanDeleter;
45
- }
46
- /** Registers both project services on the router (routes stage). */
47
- export declare function registerProjectServices(router: ConnectRouter, deps: ProjectControllerDeps): void;
48
- //# sourceMappingURL=controller.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/domain/project/controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,qBAAqB,CAAC;AAYzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,4CAA4C,CAAC;AA2CjG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAMtD,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,gBAAgB,CAAC;AAG3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kHAAkH;IAClH,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,qFAAqF;IACrF,QAAQ,CAAC,sBAAsB,EAAE,8BAA8B,GAAG,SAAS,CAAC;IAC5E;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,aAAa,CAAC;CAC7C;AAED,oEAAoE;AACpE,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,qBAAqB,GAC1B,IAAI,CAgBN"}
@@ -1,192 +0,0 @@
1
- import { create } from "@bufbuild/protobuf";
2
- import { ProjectSchema } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/api_pb";
3
- import { ProjectCommandController } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/command_pb";
4
- import { ProjectQueryController } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/query_pb";
5
- import { ProjectStatusSchema } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/status_pb";
6
- import { internalError } from "../../pipeline/errors.js";
7
- import { apiResourceKindKey } from "../../pipeline/interceptors/apiresource.js";
8
- import { newPipeline } from "../../pipeline/pipeline.js";
9
- import { callerIdentityOf } from "../../pipeline/interceptors/auth.js";
10
- import { RequestContext } from "../../pipeline/request-context.js";
11
- import { newAuthorizeStep } from "../../pipeline/steps/authorize.js";
12
- import { newGuardReservedLabelsStep } from "../../pipeline/steps/guard-reserved-labels.js";
13
- import { newBuildUpdateStateStep } from "../../pipeline/steps/build-update-state.js";
14
- import { newBuildNewStateStep } from "../../pipeline/steps/defaults.js";
15
- import { newDeleteResourceStep, newExtractResourceIdStep, newLoadExistingForDeleteStep, } from "../../pipeline/steps/delete.js";
16
- import { newCheckDuplicateStep } from "../../pipeline/steps/duplicate.js";
17
- import { newDeleteSearchIndexStep, newIndexSearchStep, } from "../../pipeline/steps/index-search.js";
18
- import { newLoadByReferenceStep } from "../../pipeline/steps/load-by-reference.js";
19
- import { EXISTING_RESOURCE_KEY, newLoadExistingStep, } from "../../pipeline/steps/load-existing.js";
20
- import { SHOULD_CREATE_KEY, newLoadForApplyStep, withResolvedApplyId, } from "../../pipeline/steps/load-for-apply.js";
21
- import { TARGET_RESOURCE_KEY, newLoadTargetStep, } from "../../pipeline/steps/load-target.js";
22
- import { newCleanupIamPoliciesStep, newCreateAuthorizationTuplesStep, } from "../../pipeline/steps/authorization-tuples.js";
23
- import { newPersistStep } from "../../pipeline/steps/persist.js";
24
- import { newNormalizeReferencesStep } from "../../pipeline/steps/references.js";
25
- import { newResolveSlugStep } from "../../pipeline/steps/slug.js";
26
- import { newValidateVisibilityStep } from "../../pipeline/steps/validate-visibility.js";
27
- import { newValidateProtoStep } from "../../pipeline/steps/validation.js";
28
- import { DEFAULT_RECONCILIATION_OPTIONS, newReconciliationService, toProtoSummary, } from "./reconcile.js";
29
- import { projectSearchExtractor } from "./search-extractor.js";
30
- /** Registers both project services on the router (routes stage). */
31
- export function registerProjectServices(router, deps) {
32
- const reconciliation = newReconciliationService({
33
- store: deps.store,
34
- orphanDeleter: deps.orphanDeleter,
35
- logger: deps.logger,
36
- });
37
- router.service(ProjectCommandController, {
38
- apply: (project, ctx) => apply(deps, reconciliation, project, ctx),
39
- create: (project, ctx) => createProject(deps, project, ctx),
40
- update: (project, ctx) => update(deps, project, ctx),
41
- delete: (projectId, ctx) => deleteProject(deps, projectId, ctx),
42
- });
43
- router.service(ProjectQueryController, {
44
- get: (projectId, ctx) => get(deps, projectId, ctx),
45
- getByReference: (ref, ctx) => getByReference(deps, ref, ctx),
46
- });
47
- }
48
- function kindOf(ctx) {
49
- return ctx.values.get(apiResourceKindKey);
50
- }
51
- /** Create — chain per Go buildCreatePipeline (create.go:54-63). */
52
- async function createProject(deps, project, ctx) {
53
- const reqCtx = new RequestContext(ProjectSchema, project, callerIdentityOf(ctx), kindOf(ctx));
54
- await newPipeline("project-create", deps.logger)
55
- .addStep(newAuthorizeStep(ProjectCommandController.method.create, deps.authorizer))
56
- .addStep(newValidateProtoStep())
57
- .addStep(newValidateVisibilityStep())
58
- .addStep(newResolveSlugStep())
59
- .addStep(newCheckDuplicateStep(deps.store))
60
- .addStep(newBuildNewStateStep())
61
- .addStep(newGuardReservedLabelsStep(deps.authorizer))
62
- .addStep(newNormalizeReferencesStep())
63
- .addStep(newPersistStep(deps.store))
64
- .addStep(newCreateAuthorizationTuplesStep(deps.authorizationLifecycle, deps.logger))
65
- .addStep(newIndexSearchStep(deps.store, projectSearchExtractor, deps.logger))
66
- .build()
67
- .execute(reqCtx);
68
- return reqCtx.newState;
69
- }
70
- /**
71
- * Update — chain per Go buildUpdatePipeline (update.go:55-62). Deliberately
72
- * narrower than create (no ValidateVisibility, no NormalizeReferences —
73
- * the asymmetry is contract; see the module header).
74
- */
75
- async function update(deps, project, ctx) {
76
- const reqCtx = new RequestContext(ProjectSchema, project, callerIdentityOf(ctx), kindOf(ctx));
77
- await newPipeline("project-update", deps.logger)
78
- .addStep(newAuthorizeStep(ProjectCommandController.method.update, deps.authorizer))
79
- .addStep(newValidateProtoStep())
80
- .addStep(newResolveSlugStep())
81
- .addStep(newLoadExistingStep(deps.store))
82
- .addStep(newBuildUpdateStateStep())
83
- .addStep(newPersistStep(deps.store))
84
- .addStep(newIndexSearchStep(deps.store, projectSearchExtractor, deps.logger))
85
- .build()
86
- .execute(reqCtx);
87
- return reqCtx.newState;
88
- }
89
- /**
90
- * Apply — declarative create-or-update PLUS membership reconciliation
91
- * (apply.go:29-85): a minimal pipeline decides existence, the previous
92
- * members are captured BEFORE delegation overwrites them, the full Create
93
- * or Update handler runs, then the reconciler diffs previous vs persisted
94
- * members and prunes orphans.
95
- *
96
- * Two ported postures:
97
- * - A reconcile failure is logged and SWALLOWED — apply still succeeds,
98
- * returning the persisted project without a summary (apply.go:77-82;
99
- * defensive in both editions — the reconciler never throws).
100
- * - On success the summary is set UNCONDITIONALLY, so every successful
101
- * apply response carries status.last_reconciliation, even as an empty
102
- * message. Response-only — never persisted.
103
- */
104
- async function apply(deps, reconciliation, project, ctx) {
105
- const reqCtx = new RequestContext(ProjectSchema, project, callerIdentityOf(ctx), kindOf(ctx));
106
- await newPipeline("project-apply", deps.logger)
107
- .addStep(newAuthorizeStep(ProjectCommandController.method.apply, deps.authorizer))
108
- .addStep(newValidateProtoStep())
109
- .addStep(newResolveSlugStep())
110
- .addStep(newLoadForApplyStep(deps.store))
111
- .build()
112
- .execute(reqCtx);
113
- const shouldCreate = reqCtx.get(SHOULD_CREATE_KEY);
114
- if (typeof shouldCreate !== "boolean") {
115
- throw internalError(new Error("apply pipeline did not set shouldCreate flag"), "apply operation failed to determine create vs update");
116
- }
117
- // Captured before Create/Update runs; on first apply (create) there are
118
- // no previous members (Go apply.go:45-50).
119
- const previousMembers = shouldCreate
120
- ? []
121
- : (reqCtx.get(EXISTING_RESOURCE_KEY)?.spec
122
- ?.members ?? []);
123
- const persisted = shouldCreate
124
- ? await createProject(deps, project, ctx)
125
- : await update(deps, withResolvedApplyId(ProjectSchema, project, reqCtx), ctx);
126
- const currentMembers = persisted.spec?.members ?? [];
127
- try {
128
- const result = await reconciliation.reconcile(previousMembers, currentMembers, DEFAULT_RECONCILIATION_OPTIONS);
129
- persisted.status ??= create(ProjectStatusSchema);
130
- persisted.status.lastReconciliation = toProtoSummary(result);
131
- }
132
- catch (error) {
133
- deps.logger.error("Reconciliation failed", {
134
- projectId: persisted.metadata?.id ?? "",
135
- error: error instanceof Error ? error.message : String(error),
136
- });
137
- }
138
- return persisted;
139
- }
140
- /**
141
- * Delete — returns the pre-delete resource (delete.go). Deletes ONLY the
142
- * project entity: member resources are never cascaded.
143
- */
144
- async function deleteProject(deps, projectId, ctx) {
145
- const reqCtx = new RequestContext(ProjectCommandController.method.delete.input, projectId, callerIdentityOf(ctx), kindOf(ctx));
146
- await newPipeline("project-delete", deps.logger)
147
- .addStep(newAuthorizeStep(ProjectCommandController.method.delete, deps.authorizer))
148
- .addStep(newValidateProtoStep())
149
- .addStep(newExtractResourceIdStep())
150
- .addStep(newLoadExistingForDeleteStep(deps.store, ProjectSchema))
151
- .addStep(newDeleteResourceStep(deps.store))
152
- .addStep(newCleanupIamPoliciesStep(deps.authorizationLifecycle, deps.logger))
153
- .addStep(newDeleteSearchIndexStep(deps.store, deps.logger))
154
- .build()
155
- .execute(reqCtx);
156
- const deleted = reqCtx.get(EXISTING_RESOURCE_KEY);
157
- if (deleted === undefined) {
158
- // Go puts this text ON THE WIRE (delete.go:43, InternalError(nil, …));
159
- // the arm is unreachable in practice but the copy is byte-pinned.
160
- throw internalError(new Error("delete pipeline completed without a loaded resource"), "deleted project not found in context");
161
- }
162
- return deleted;
163
- }
164
- /** Get — LoadTarget by id; NotFound when absent (get.go). */
165
- async function get(deps, projectId, ctx) {
166
- const reqCtx = new RequestContext(ProjectQueryController.method.get.input, projectId, callerIdentityOf(ctx), kindOf(ctx));
167
- await newPipeline("project-get", deps.logger)
168
- .addStep(newAuthorizeStep(ProjectQueryController.method.get, deps.authorizer))
169
- .addStep(newValidateProtoStep())
170
- .addStep(newLoadTargetStep(deps.store, ProjectSchema))
171
- .build()
172
- .execute(reqCtx);
173
- return reqCtx.get(TARGET_RESOURCE_KEY);
174
- }
175
- /**
176
- * GetByReference — slug lookup within an org (get_by_reference.go). Project
177
- * is org-scoped, so an empty-org reference is rejected InvalidArgument by
178
- * the shared step's kind_meta scope check — a bare slug is under-specified,
179
- * never a global search (the conformance suite pins this; Go's file-level
180
- * doc comment claiming a platform-scoped fallback is stale).
181
- */
182
- async function getByReference(deps, ref, ctx) {
183
- const reqCtx = new RequestContext(ProjectQueryController.method.getByReference.input, ref, callerIdentityOf(ctx), kindOf(ctx));
184
- await newPipeline("project-get-by-reference", deps.logger)
185
- .addStep(newAuthorizeStep(ProjectQueryController.method.getByReference, deps.authorizer))
186
- .addStep(newValidateProtoStep())
187
- .addStep(newLoadByReferenceStep(deps.store, ProjectSchema))
188
- .build()
189
- .execute(reqCtx);
190
- return reqCtx.get(TARGET_RESOURCE_KEY);
191
- }
192
- //# sourceMappingURL=controller.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/domain/project/controller.ts"],"names":[],"mappings":"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"}
@@ -1,77 +0,0 @@
1
- import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
2
- import type { ApiResourceReference } from "@stigmer/protos/ai/stigmer/commons/apiresource/io_pb";
3
- import type { ReconciliationSummary } from "@stigmer/protos/ai/stigmer/tenancy/project/v1/status_pb";
4
- import type { Logger } from "../../boot/logger.js";
5
- import type { Store } from "../../store/interface.js";
6
- /**
7
- * Deletes one orphaned resource by kind and id — Go's ResourceDeleter, the
8
- * only execution capability the reference model needs (resources are
9
- * created/updated individually by the CLI; the server only deletes orphans).
10
- * Implemented over the four in-process command clients (boot/inprocess.ts).
11
- */
12
- export interface OrphanDeleter {
13
- delete(kind: ApiResourceKind, resourceId: string): Promise<void>;
14
- }
15
- /**
16
- * Go ReconciliationOptions, reduced to the two flags the algorithm reads.
17
- * Production always passes DEFAULT_RECONCILIATION_OPTIONS; the other
18
- * combinations remain reachable for tests because the branches are part of
19
- * the ported algorithm.
20
- */
21
- export interface ReconciliationOptions {
22
- /** When true, orphaned resources are deleted (Go default). */
23
- readonly pruneEnabled: boolean;
24
- /** When true, the plan is computed but nothing is deleted. */
25
- readonly dryRun: boolean;
26
- }
27
- export declare const DEFAULT_RECONCILIATION_OPTIONS: ReconciliationOptions;
28
- /** One per-orphan failure — log-only, never wire-visible (Go, verified). */
29
- export interface ReconciliationError {
30
- /** "{kind}:{slug}" of the orphan that failed. */
31
- readonly resourceKey: string;
32
- readonly message: string;
33
- readonly cause: unknown;
34
- }
35
- /** Go ReconciliationResult, as a plain immutable value. */
36
- export interface ReconciliationResult {
37
- /** References in current but not previous — newly associated members. */
38
- readonly added: ReadonlyArray<ApiResourceReference>;
39
- /**
40
- * Orphans successfully deleted (or, on a dry run, the orphans that WOULD
41
- * be deleted — Go reports them in the same slot without deleting).
42
- */
43
- readonly removed: ReadonlyArray<ApiResourceReference>;
44
- readonly errors: ReadonlyArray<ReconciliationError>;
45
- }
46
- export interface ReconciliationService {
47
- /**
48
- * Compares memberships and prunes orphans per the options. NEVER throws —
49
- * Go's implementation always returns a nil error; failures ride
50
- * result.errors (and the apply handler's error-swallow arm upstream is
51
- * therefore defensive dead code in both editions, ported anyway).
52
- */
53
- reconcile(previousMembers: ReadonlyArray<ApiResourceReference>, currentMembers: ReadonlyArray<ApiResourceReference>, options: ReconciliationOptions): Promise<ReconciliationResult>;
54
- }
55
- export interface ReconciliationServiceDeps {
56
- readonly store: Store;
57
- /**
58
- * Lazy per the compose root's boot-ordering idiom: the in-process clients
59
- * behind the deleter exist only after routes registration completes.
60
- */
61
- readonly orphanDeleter: () => OrphanDeleter;
62
- readonly logger: Logger;
63
- }
64
- export declare function newReconciliationService(deps: ReconciliationServiceDeps): ReconciliationService;
65
- /**
66
- * "{kind}:{slug}" with the kind's enum NAME — Go fmt %s of the enum (e.g.
67
- * "agent:my-agent", "mcp_server:tools"). The numeric form would diverge
68
- * from Go's log/error copy.
69
- */
70
- export declare function referenceKey(ref: ApiResourceReference): string;
71
- /**
72
- * Go ToProtoSummary: added → created, updated ALWAYS empty (not applicable
73
- * in the reference model), removed → deleted. Every successful apply sets
74
- * the summary — even an all-empty one is a PRESENT message on the wire.
75
- */
76
- export declare function toProtoSummary(result: ReconciliationResult): ReconciliationSummary;
77
- //# sourceMappingURL=reconcile.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../../src/domain/project/reconcile.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AACtH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sDAAsD,CAAC;AAEjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yDAAyD,CAAC;AAErG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,8BAA8B,EAAE,qBAG5C,CAAC;AAEF,4EAA4E;AAC5E,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,2DAA2D;AAC3D,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACpD;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,SAAS,CACP,eAAe,EAAE,aAAa,CAAC,oBAAoB,CAAC,EACpD,cAAc,EAAE,aAAa,CAAC,oBAAoB,CAAC,EACnD,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,aAAa,CAAC;IAC5C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,yBAAyB,GAC9B,qBAAqB,CA+BvB;AAmHD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,CAE9D;AAYD;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,oBAAoB,GAC3B,qBAAqB,CAMvB"}