@cat-factory/server 0.239.2 → 0.241.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 (40) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/promptFragments/PromptFragmentsInternalController.d.ts +9 -0
  6. package/dist/modules/promptFragments/PromptFragmentsInternalController.d.ts.map +1 -1
  7. package/dist/modules/promptFragments/PromptFragmentsInternalController.js +100 -0
  8. package/dist/modules/promptFragments/PromptFragmentsInternalController.js.map +1 -1
  9. package/dist/modules/publicApi/PublicApiController.js +19 -19
  10. package/dist/modules/publicApi/PublicApiController.js.map +1 -1
  11. package/dist/modules/publicApi/PublicDebugController.js +9 -9
  12. package/dist/modules/publicApi/PublicDebugController.js.map +1 -1
  13. package/dist/modules/publicApi/PublicDecisionController.js +1 -1
  14. package/dist/modules/publicApi/PublicDecisionController.js.map +1 -1
  15. package/dist/modules/publicApi/PublicDiscoveryController.js +2 -2
  16. package/dist/modules/publicApi/PublicDiscoveryController.js.map +1 -1
  17. package/dist/modules/publicApi/PublicEvidenceController.d.ts.map +1 -1
  18. package/dist/modules/publicApi/PublicEvidenceController.js +30 -9
  19. package/dist/modules/publicApi/PublicEvidenceController.js.map +1 -1
  20. package/dist/modules/publicApi/PublicKeyController.d.ts.map +1 -1
  21. package/dist/modules/publicApi/PublicKeyController.js +4 -4
  22. package/dist/modules/publicApi/PublicKeyController.js.map +1 -1
  23. package/dist/modules/publicApi/PublicNotificationWebhookController.js +3 -3
  24. package/dist/modules/publicApi/PublicNotificationWebhookController.js.map +1 -1
  25. package/dist/modules/publicApi/decisions/scope.d.ts.map +1 -1
  26. package/dist/modules/publicApi/decisions/scope.js +3 -1
  27. package/dist/modules/publicApi/decisions/scope.js.map +1 -1
  28. package/dist/modules/publicApi/openapiDocument.generated.d.ts +1 -1
  29. package/dist/modules/publicApi/openapiDocument.generated.d.ts.map +1 -1
  30. package/dist/modules/publicApi/openapiDocument.generated.js +1 -1
  31. package/dist/modules/publicApi/openapiDocument.generated.js.map +1 -1
  32. package/dist/modules/serviceSpec/ServiceSpecController.d.ts +6 -1
  33. package/dist/modules/serviceSpec/ServiceSpecController.d.ts.map +1 -1
  34. package/dist/modules/serviceSpec/ServiceSpecController.js +21 -2
  35. package/dist/modules/serviceSpec/ServiceSpecController.js.map +1 -1
  36. package/dist/persistence/deploymentDocuments.d.ts +42 -0
  37. package/dist/persistence/deploymentDocuments.d.ts.map +1 -0
  38. package/dist/persistence/deploymentDocuments.js +96 -0
  39. package/dist/persistence/deploymentDocuments.js.map +1 -0
  40. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"openapiDocument.generated.js","sourceRoot":"","sources":["../../../src/modules/publicApi/openapiDocument.generated.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,EAAE;AACF,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,8EAA8E;AAE9E,MAAM,CAAC,MAAM,YAAY,GAAG,wluZAAwluZ,CAAA"}
1
+ {"version":3,"file":"openapiDocument.generated.js","sourceRoot":"","sources":["../../../src/modules/publicApi/openapiDocument.generated.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,EAAE;AACF,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,8EAA8E;AAE9E,MAAM,CAAC,MAAM,YAAY,GAAG,q2hbAAq2hb,CAAA"}
@@ -8,9 +8,14 @@ import type { AppEnv } from '../../http/env.js';
8
8
  *
9
9
  * It resolves the block's repo through the same `resolveRunRepoContext` seam the engine uses
10
10
  * to bind a run's pre/post-ops (installation + repo + default branch), so it is
11
- * runtime-symmetric both facades wire the resolver. When GitHub isn't connected (no
11
+ * runtime-symmetric: both facades wire the resolver. When GitHub isn't connected (no
12
12
  * resolver, no linked repo) or no spec exists yet, it returns `{ present: false }` so the
13
13
  * window shows an empty state instead of erroring. Mounted under `/workspaces/:workspaceId`.
14
+ *
15
+ * It also serves the RUN-scoped read beside it. Both are spec reads and the pair belongs
16
+ * together precisely so nobody reaches for the wrong one: this default-branch read answers
17
+ * "what does this service require", and `/executions/:executionId/spec` answers "what did this
18
+ * run rule on", which is a different tree for as long as the run's pull request is open.
14
19
  */
15
20
  export declare function serviceSpecController(): Hono<AppEnv>;
16
21
  //# sourceMappingURL=ServiceSpecController.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceSpecController.d.ts","sourceRoot":"","sources":["../../../src/modules/serviceSpec/ServiceSpecController.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAM/C;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,MAAM,CAAC,CA0BpD"}
1
+ {"version":3,"file":"ServiceSpecController.d.ts","sourceRoot":"","sources":["../../../src/modules/serviceSpec/ServiceSpecController.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAM/C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAAC,MAAM,CAAC,CAyCpD"}
@@ -1,4 +1,4 @@
1
- import { EMPTY_SERVICE_SPEC_VIEW, getServiceSpecContract } from '@cat-factory/contracts';
1
+ import { EMPTY_SERVICE_SPEC_VIEW, getRunSpecContract, getServiceSpecContract, } from '@cat-factory/contracts';
2
2
  import { buildHonoRoute } from '@toad-contracts/hono';
3
3
  import { Hono } from 'hono';
4
4
  import { param } from '../../http/params.js';
@@ -12,9 +12,14 @@ const EMPTY = EMPTY_SERVICE_SPEC_VIEW;
12
12
  *
13
13
  * It resolves the block's repo through the same `resolveRunRepoContext` seam the engine uses
14
14
  * to bind a run's pre/post-ops (installation + repo + default branch), so it is
15
- * runtime-symmetric both facades wire the resolver. When GitHub isn't connected (no
15
+ * runtime-symmetric: both facades wire the resolver. When GitHub isn't connected (no
16
16
  * resolver, no linked repo) or no spec exists yet, it returns `{ present: false }` so the
17
17
  * window shows an empty state instead of erroring. Mounted under `/workspaces/:workspaceId`.
18
+ *
19
+ * It also serves the RUN-scoped read beside it. Both are spec reads and the pair belongs
20
+ * together precisely so nobody reaches for the wrong one: this default-branch read answers
21
+ * "what does this service require", and `/executions/:executionId/spec` answers "what did this
22
+ * run rule on", which is a different tree for as long as the run's pull request is open.
18
23
  */
19
24
  export function serviceSpecController() {
20
25
  const app = new Hono();
@@ -43,6 +48,20 @@ export function serviceSpecController() {
43
48
  return c.json(EMPTY, 200);
44
49
  }
45
50
  });
51
+ // The spec ONE RUN was judged against, for the outcome card's requirement join. Delegated
52
+ // whole to the engine's evidence loader rather than resolved here: the branch rule, the
53
+ // tester gate and the per-run memo are the same three the verification report and
54
+ // `GET /api/v1/runs/:runId/outcome` read through, and a second reader with its own copy of
55
+ // any of them is how the card and the endpoint came to describe one run differently.
56
+ buildHonoRoute(app, getRunSpecContract, async (c) => {
57
+ const view = await c
58
+ .get('container')
59
+ .executionService.readRunSpec(param(c, 'workspaceId'), c.req.valid('param').executionId);
60
+ // A run this workspace does not have is the same answer as a run whose spec cannot be read:
61
+ // there is no tree to join against, and the card states that as `spec: 'not_read'`. It is
62
+ // NOT a 404, because the card asks this question about a run it is already rendering.
63
+ return c.json(view ?? EMPTY, 200);
64
+ });
46
65
  return app;
47
66
  }
48
67
  //# sourceMappingURL=ServiceSpecController.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ServiceSpecController.js","sourceRoot":"","sources":["../../../src/modules/serviceSpec/ServiceSpecController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,KAAK,GAAG,uBAAuB,CAAA;AAErC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpC,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvC,IAAI,GAAG,CAAA;QACP,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,qFAAqF;YACrF,yEAAyE;YACzE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC3B,CAAC;QACD,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACnC,yFAAyF;QACzF,uFAAuF;QACvF,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAA;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"ServiceSpecController.js","sourceRoot":"","sources":["../../../src/modules/serviceSpec/ServiceSpecController.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAErD,MAAM,KAAK,GAAG,uBAAuB,CAAA;AAErC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAU,CAAA;IAE9B,cAAc,CAAC,GAAG,EAAE,sBAAsB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QACtD,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACpC,MAAM,OAAO,GAAG,SAAS,CAAC,qBAAqB,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACvC,IAAI,GAAG,CAAA;QACP,IAAI,CAAC;YACH,GAAG,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAA;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,qFAAqF;YACrF,yEAAyE;YACzE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC3B,CAAC;QACD,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACnC,yFAAyF;QACzF,uFAAuF;QACvF,IAAI,CAAC;YACH,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,eAAe,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,CAAA;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,0FAA0F;IAC1F,wFAAwF;IACxF,kFAAkF;IAClF,2FAA2F;IAC3F,qFAAqF;IACrF,cAAc,CAAC,GAAG,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;QAClD,MAAM,IAAI,GAAG,MAAM,CAAC;aACjB,GAAG,CAAC,WAAW,CAAC;aAChB,gBAAgB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,aAAa,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAA;QAC1F,4FAA4F;QAC5F,0FAA0F;QAC1F,sFAAsF;QACtF,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,GAAG,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type { DeploymentDocumentResolver, DocumentContent, DocumentSourceKind } from '@cat-factory/kernel';
2
+ /**
3
+ * A {@link DeploymentDocumentResolver} backed by the mothership's
4
+ * `POST /internal/prompt-fragments/document-bodies`, presenting the node's machine token.
5
+ *
6
+ * **The credential never crosses; the BODY does.** The deployment's document credentials live in
7
+ * the mothership's environment, and `ENCRYPTION_KEY`-class configuration does not reach a laptop,
8
+ * so a node cannot authenticate to the vendor itself. That is the same rule that keeps a
9
+ * decrypting repository off the remote route, applied to a resolver instead of a repository.
10
+ *
11
+ * **A failed read THROWS; it never answers "no such document".** An unreachable mothership and a
12
+ * document this deployment cannot resolve are the same value and opposite facts, and the caller
13
+ * (`FragmentLibraryService.resolveDocumentBody`) degrades a THROW to the fragment's registered
14
+ * body with a warning naming the fragment. Answering silently-absent instead would produce the
15
+ * identical prompt with no warning anywhere, which is exactly the stale-standard failure that is
16
+ * indistinguishable from a current one.
17
+ */
18
+ export declare class HttpDeploymentDocumentResolver implements DeploymentDocumentResolver {
19
+ private readonly opts;
20
+ constructor(opts: {
21
+ baseUrl: string;
22
+ /** Fixed token, or a provider read PER REQUEST (the shape every other machine client takes). */
23
+ token: string | (() => string | null);
24
+ /**
25
+ * The sources the MOTHERSHIP has configured, as reported at connect time.
26
+ *
27
+ * A node cannot see the mothership's environment, so `configured()` would otherwise have to
28
+ * be a network call, and it is asked on a hot path (per document-backed entry, per catalog
29
+ * resolve) by a caller that only wants to know whether to bother. Absent ⇒ assume every
30
+ * deployment-scopable source may be served and let the read itself decide, which is the safe
31
+ * direction: it costs one round trip that returns nothing, where the opposite would silently
32
+ * skip a document the mothership could have served.
33
+ */
34
+ configuredSources?: readonly DocumentSourceKind[];
35
+ fetchImpl?: typeof fetch;
36
+ });
37
+ configured(source: DocumentSourceKind): boolean;
38
+ fetch(source: DocumentSourceKind, externalId: string): Promise<DocumentContent>;
39
+ probeVersion(source: DocumentSourceKind, externalId: string): Promise<string>;
40
+ private read;
41
+ }
42
+ //# sourceMappingURL=deploymentDocuments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploymentDocuments.d.ts","sourceRoot":"","sources":["../../src/persistence/deploymentDocuments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,eAAe,EACf,kBAAkB,EACnB,MAAM,qBAAqB,CAAA;AAU5B;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,8BAA+B,YAAW,0BAA0B;IAE7E,OAAO,CAAC,QAAQ,CAAC,IAAI;IADvB,YACmB,IAAI,EAAE;QACrB,OAAO,EAAE,MAAM,CAAA;QACf,gGAAgG;QAChG,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,CAAA;QACrC;;;;;;;;;WASG;QACH,iBAAiB,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAA;QACjD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;KACzB,EACC;IAEJ,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAG9C;IAEK,KAAK,CAAC,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CASpF;IAEK,YAAY,CAAC,MAAM,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAKlF;YAEa,IAAI;CA8DnB"}
@@ -0,0 +1,96 @@
1
+ import { UnavailableError, describeError } from '@cat-factory/kernel';
2
+ import { isDeploymentScopedSource } from '@cat-factory/contracts';
3
+ import { documentBodyRefKey } from '../modules/promptFragments/PromptFragmentsInternalController.js';
4
+ // The client half of the mothership-mode DEPLOYMENT-scoped document read (see
5
+ // `../modules/promptFragments/PromptFragmentsInternalController.ts` for why the body crosses the
6
+ // machine API rather than the credential). The sibling of `promptFragments.ts` and
7
+ // `foundationalBuiltins.ts`, written to the same contract for the same reason.
8
+ /**
9
+ * A {@link DeploymentDocumentResolver} backed by the mothership's
10
+ * `POST /internal/prompt-fragments/document-bodies`, presenting the node's machine token.
11
+ *
12
+ * **The credential never crosses; the BODY does.** The deployment's document credentials live in
13
+ * the mothership's environment, and `ENCRYPTION_KEY`-class configuration does not reach a laptop,
14
+ * so a node cannot authenticate to the vendor itself. That is the same rule that keeps a
15
+ * decrypting repository off the remote route, applied to a resolver instead of a repository.
16
+ *
17
+ * **A failed read THROWS; it never answers "no such document".** An unreachable mothership and a
18
+ * document this deployment cannot resolve are the same value and opposite facts, and the caller
19
+ * (`FragmentLibraryService.resolveDocumentBody`) degrades a THROW to the fragment's registered
20
+ * body with a warning naming the fragment. Answering silently-absent instead would produce the
21
+ * identical prompt with no warning anywhere, which is exactly the stale-standard failure that is
22
+ * indistinguishable from a current one.
23
+ */
24
+ export class HttpDeploymentDocumentResolver {
25
+ opts;
26
+ constructor(opts) {
27
+ this.opts = opts;
28
+ }
29
+ configured(source) {
30
+ if (!isDeploymentScopedSource(source))
31
+ return false;
32
+ return this.opts.configuredSources?.includes(source) ?? true;
33
+ }
34
+ async fetch(source, externalId) {
35
+ const content = await this.read(source, externalId);
36
+ return {
37
+ externalId,
38
+ title: '',
39
+ url: '',
40
+ body: content.body,
41
+ version: content.version,
42
+ };
43
+ }
44
+ async probeVersion(source, externalId) {
45
+ // The mothership's own resolver caches the body, so this is not the extra fetch it looks
46
+ // like: the node's `documentBodyCache` asks for a version only when its entry enters the
47
+ // refresh window, and the mothership answers from the copy it just verified.
48
+ return (await this.read(source, externalId)).version;
49
+ }
50
+ async read(source, externalId) {
51
+ const fetchImpl = this.opts.fetchImpl ?? fetch;
52
+ const token = typeof this.opts.token === 'function' ? this.opts.token() : this.opts.token;
53
+ const url = `${this.opts.baseUrl.replace(/\/$/, '')}/internal/prompt-fragments/document-bodies`;
54
+ let res;
55
+ try {
56
+ res = await fetchImpl(url, {
57
+ method: 'POST',
58
+ headers: {
59
+ authorization: `Bearer ${token ?? ''}`,
60
+ 'content-type': 'application/json',
61
+ },
62
+ body: JSON.stringify({ refs: [{ source, externalId }] }),
63
+ });
64
+ }
65
+ catch (error) {
66
+ throw new UnavailableError('A deployment-scoped document could not be read from the mothership', 'deployment_document_unreachable',
67
+ // Scrubbed through `redactSecrets`, because a fetch failure routinely echoes the request
68
+ // URL, which here carries the mothership's address.
69
+ describeError(error));
70
+ }
71
+ if (!res.ok) {
72
+ // Includes a mothership OLDER than this node, which answers 404 for a route it does not
73
+ // serve. Reading that as "the document is gone" would silently pin the registered body.
74
+ throw new UnavailableError('The mothership refused a deployment-scoped document read', 'deployment_document_unreachable', { status: res.status });
75
+ }
76
+ const payload = (await res.json().catch(() => null));
77
+ const bodies = payload?.bodies;
78
+ if (!bodies || typeof bodies !== 'object' || Array.isArray(bodies)) {
79
+ throw new UnavailableError('The mothership returned an unreadable deployment-document reply', 'deployment_document_unreachable', { field: 'bodies' });
80
+ }
81
+ // Indexed with the SERVER's own key function, never a locally re-spelled one: the pair
82
+ // `(source, externalId)` is what identifies a document, and a client that rebuilds that
83
+ // string itself is one rename away from silently indexing nothing.
84
+ const entry = bodies[documentBodyRefKey(source, externalId)];
85
+ const body = entry?.body;
86
+ const version = entry?.version;
87
+ if (typeof body !== 'string' || typeof version !== 'string') {
88
+ // ABSENT means the mothership could not resolve it either (it omits rather than failing the
89
+ // whole batch, and logs why on its own side). Throwing keeps the node's disposition the same
90
+ // as a standalone deployment's: degrade to the registered body AND say so.
91
+ throw new UnavailableError('The mothership could not resolve this deployment-scoped document', 'deployment_document_unresolved', { source });
92
+ }
93
+ return { body, version };
94
+ }
95
+ }
96
+ //# sourceMappingURL=deploymentDocuments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploymentDocuments.js","sourceRoot":"","sources":["../../src/persistence/deploymentDocuments.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/server",
3
- "version": "0.239.2",
3
+ "version": "0.241.0",
4
4
  "description": "Runtime-neutral HTTP layer for the Agent Architecture Board: the Hono controllers, middleware (auth/authz/CORS/error), request helpers and the gateway seams shared by every deployment facade (Cloudflare Worker, Node service).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,13 +31,13 @@
31
31
  "jose": "^6.2.8",
32
32
  "pino": "^10.3.1",
33
33
  "valibot": "^1.4.2",
34
- "@cat-factory/contracts": "0.261.1",
35
- "@cat-factory/integrations": "0.140.2",
36
- "@cat-factory/mcp-server": "0.16.1",
37
- "@cat-factory/agents": "0.116.8",
38
- "@cat-factory/kernel": "0.261.0",
39
- "@cat-factory/orchestration": "0.229.0",
40
- "@cat-factory/spend": "0.15.27"
34
+ "@cat-factory/agents": "0.117.1",
35
+ "@cat-factory/kernel": "0.262.1",
36
+ "@cat-factory/integrations": "0.141.1",
37
+ "@cat-factory/mcp-server": "0.17.0",
38
+ "@cat-factory/contracts": "0.263.0",
39
+ "@cat-factory/orchestration": "0.231.0",
40
+ "@cat-factory/spend": "0.15.29"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^26.1.2",