@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.
- package/dist/authorization/model/index.d.ts +1 -1
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +0 -2
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/organization.d.ts.map +1 -1
- package/dist/authorization/model/organization.js +0 -1
- package/dist/authorization/model/organization.js.map +1 -1
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +2 -15
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/inprocess.d.ts +2 -13
- package/dist/boot/inprocess.d.ts.map +1 -1
- package/dist/boot/inprocess.js +6 -16
- package/dist/boot/inprocess.js.map +1 -1
- package/dist/domain/workflow/registry/data/task-kind-registry.json +0 -1
- package/dist/pipeline/interceptors/auth.d.ts +1 -1
- package/dist/pipeline/interceptors/auth.js +1 -1
- package/dist/query/search/registry.d.ts +3 -5
- package/dist/query/search/registry.d.ts.map +1 -1
- package/dist/query/search/registry.js +3 -7
- package/dist/query/search/registry.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +3 -1
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +19 -1
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +3 -1
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +22 -1
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/__tests__/derived-tuples.test.ts +1 -1
- package/src/authorization/__tests__/fixtures/fga/org-admin-owner-inheritance.fga.yaml +6 -6
- package/src/authorization/__tests__/wire-permissions.test.ts +0 -1
- package/src/authorization/model/__tests__/registry.test.ts +0 -9
- package/src/authorization/model/index.ts +1 -3
- package/src/authorization/model/organization.ts +0 -1
- package/src/boot/compose.ts +2 -15
- package/src/boot/inprocess.ts +8 -29
- package/src/domain/iampolicy/__tests__/role-lifecycle.test.ts +0 -1
- package/src/domain/workflow/registry/data/task-kind-registry.json +0 -1
- package/src/pipeline/__tests__/router-transport.test.ts +1 -1
- package/src/pipeline/interceptors/auth.ts +1 -1
- package/src/query/__tests__/query-services.test.ts +16 -18
- package/src/query/search/__tests__/criteria.test.ts +3 -6
- package/src/query/search/__tests__/query-store.test.ts +21 -21
- package/src/query/search/registry.ts +3 -7
- package/src/store/postgres/__tests__/migrations.test.ts +23 -4
- package/src/store/postgres/migrations.ts +20 -1
- package/src/store/sqlite/__tests__/migrations.test.ts +26 -2
- package/src/store/sqlite/migrations.ts +23 -1
- package/dist/authorization/model/project.d.ts +0 -2
- package/dist/authorization/model/project.d.ts.map +0 -1
- package/dist/authorization/model/project.js +0 -32
- package/dist/authorization/model/project.js.map +0 -1
- package/dist/domain/project/controller.d.ts +0 -48
- package/dist/domain/project/controller.d.ts.map +0 -1
- package/dist/domain/project/controller.js +0 -192
- package/dist/domain/project/controller.js.map +0 -1
- package/dist/domain/project/reconcile.d.ts +0 -77
- package/dist/domain/project/reconcile.d.ts.map +0 -1
- package/dist/domain/project/reconcile.js +0 -179
- package/dist/domain/project/reconcile.js.map +0 -1
- package/dist/domain/project/search-extractor.d.ts +0 -3
- package/dist/domain/project/search-extractor.d.ts.map +0 -1
- package/dist/domain/project/search-extractor.js +0 -43
- package/dist/domain/project/search-extractor.js.map +0 -1
- package/src/authorization/model/project.ts +0 -47
- package/src/domain/project/__tests__/project.composed.test.ts +0 -381
- package/src/domain/project/__tests__/reconcile.test.ts +0 -447
- package/src/domain/project/controller.ts +0 -387
- package/src/domain/project/reconcile.ts +0 -296
- 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
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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+
|
|
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 =
|
|
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 =
|
|
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 +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"}
|