dominus-sdk-nodejs 11.0.5 → 11.0.7
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/README.md +351 -351
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/namespaces/artifacts.d.ts.map +1 -1
- package/dist/namespaces/artifacts.js +13 -2
- package/dist/namespaces/artifacts.js.map +1 -1
- package/dist/namespaces/browser.d.ts +2 -0
- package/dist/namespaces/browser.d.ts.map +1 -1
- package/dist/namespaces/browser.js.map +1 -1
- package/dist/namespaces/recipes.d.ts +17 -1
- package/dist/namespaces/recipes.d.ts.map +1 -1
- package/dist/namespaces/recipes.js +23 -2
- package/dist/namespaces/recipes.js.map +1 -1
- package/dist/refs/grammar.d.ts +54 -0
- package/dist/refs/grammar.d.ts.map +1 -0
- package/dist/refs/grammar.js +179 -0
- package/dist/refs/grammar.js.map +1 -0
- package/dist/refs/resolve.d.ts +49 -0
- package/dist/refs/resolve.d.ts.map +1 -0
- package/dist/refs/resolve.js +129 -0
- package/dist/refs/resolve.js.map +1 -0
- package/dist/refs/types.d.ts +56 -0
- package/dist/refs/types.d.ts.map +1 -0
- package/dist/refs/types.js +15 -0
- package/dist/refs/types.js.map +1 -0
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/00-reading-order.md +35 -35
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/01-purpose-and-boundaries.md +48 -48
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/02-repo-map-and-entrypoints.md +46 -46
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/03-api-surface.md +59 -59
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/04-data-state-and-storage.md +36 -36
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/05-integrations-and-runtime.md +40 -40
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/06-workflows-commands-and-ci.md +58 -58
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/07-operations-release-and-live-proof.md +40 -40
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/08-security-privacy-and-secrets.md +38 -38
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/09-known-risks-and-debt.md +34 -34
- package/docs/agent-guide/2026-06-27-0849-sdk-orient/10-agent-playbook.md +48 -48
- package/docs/agent-guide/2026-08-04-sdk-nodejs/00-reading-order.md +11 -11
- package/docs/agent-guide/2026-08-04-sdk-nodejs/01-purpose-and-boundaries.md +14 -14
- package/docs/agent-guide/2026-08-04-sdk-nodejs/03-api-surface.md +16 -16
- package/docs/agent-guide/2026-08-04-sdk-nodejs/10-agent-playbook.md +14 -14
- package/docs/agent-guide/INDEX.md +14 -14
- package/docs/agent-guide/current.md +22 -22
- package/docs/architecture.md +119 -119
- package/docs/atlas/2026-07-24-1231-sdk-nodejs-blockers.md +15 -15
- package/docs/atlas/2026-07-24-1231-sdk-nodejs-proof-ladder.md +25 -25
- package/docs/atlas/2026-07-24-1231-sdk-nodejs-truthmap.md +43 -43
- package/docs/atlas/2026-08-04-sdk-nodejs-blockers.md +12 -12
- package/docs/atlas/2026-08-04-sdk-nodejs-proof-ladder.md +9 -9
- package/docs/atlas/2026-08-04-sdk-nodejs-truthmap.md +21 -21
- package/docs/atlas/INDEX.md +26 -26
- package/docs/janitor/2026-06-27-0849-sdk-orient-cleanup-audit.md +102 -102
- package/docs/janitor/2026-08-04-sdk-nodejs-cleanup-audit.md +14 -14
- package/docs/plans/2026-08-04-pending-work-fruition-summary.md +46 -46
- package/docs/routes-services.md +85 -80
- package/docs/usage-reference.md +713 -698
- package/docs/workflow-hard-cut-release.md +24 -24
- package/package.json +55 -55
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref grammar — the single Node-side definition of every ref scheme's grammar.
|
|
3
|
+
*
|
|
4
|
+
* `parse()` owns grammar and does NO I/O: no network, no client, no env. Scope,
|
|
5
|
+
* tier, authorization, and existence are validated by the owning services, never
|
|
6
|
+
* here. `routeFor()` is the serialization inverse used by the transport layer
|
|
7
|
+
* (and by the E3 round-trip totality property) to rebuild a recipe route path.
|
|
8
|
+
*
|
|
9
|
+
* Schemes:
|
|
10
|
+
* - `ar://{group}/{owner}/{environment}/{kind}/{artifactKey}[@vN]` (5-segment v2)
|
|
11
|
+
* - `ar://{projectSlug}/{environment}/{namespace}/{artifactKey}[@vN]` (4-segment legacy)
|
|
12
|
+
* - `recipe://{type}/{name}[@{vN|N|head|latest}][?tier={tier}]`
|
|
13
|
+
* - `stash://`, `warden://`, `wf://` parse to an `unresolvable` variant carrying
|
|
14
|
+
* the missing service-owned contract and its owning service.
|
|
15
|
+
*
|
|
16
|
+
* Invalid grammar throws `ref.grammar.invalid`.
|
|
17
|
+
*/
|
|
18
|
+
import { DominusError, ValidationError } from '../lib/errors.js';
|
|
19
|
+
const AR_PREFIX = 'ar://';
|
|
20
|
+
const RECIPE_PREFIX = 'recipe://';
|
|
21
|
+
/** `type`/`name` charset, mirrors `dominus-recipe-worker/src/routes/recipes.ts` `assertName`. */
|
|
22
|
+
const RECIPE_NAME_CHARSET = /^[a-z][a-z0-9_-]{0,127}$/;
|
|
23
|
+
/** `ar://` version suffix is `@vN` only (mirrors `parseArtifactRef`). */
|
|
24
|
+
const AR_VERSION_SUFFIX_RE = /^v\d+$/;
|
|
25
|
+
const UNRESOLVABLE = {
|
|
26
|
+
stash: {
|
|
27
|
+
missingContract: 'no server-owned stash:// grammar; only the kind registry knows which scope axes a kind requires',
|
|
28
|
+
owningService: 'stash-worker',
|
|
29
|
+
},
|
|
30
|
+
warden: {
|
|
31
|
+
missingContract: "admin-only (allowed_systems: ['admin']) and no published grammar",
|
|
32
|
+
owningService: 'warden',
|
|
33
|
+
},
|
|
34
|
+
wf: {
|
|
35
|
+
missingContract: 'Execution plane',
|
|
36
|
+
owningService: 'Authority / workflow-manager',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
function grammarInvalid(detail) {
|
|
40
|
+
throw new ValidationError(`Invalid ref: ${detail}`, 400, {
|
|
41
|
+
code: 'ref.grammar.invalid',
|
|
42
|
+
category: 'validation',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/** `head`, `latest`, or a positive integer (`vN` / bare `N`) — mirrors the recipe route. */
|
|
46
|
+
function isValidRecipeVersion(raw) {
|
|
47
|
+
if (raw === 'head' || raw === 'latest') {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const numeric = raw.startsWith('v') ? raw.slice(1) : raw;
|
|
51
|
+
if (!/^\d+$/.test(numeric)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const value = Number(numeric);
|
|
55
|
+
return Number.isInteger(value) && value >= 1;
|
|
56
|
+
}
|
|
57
|
+
function parseAr(input) {
|
|
58
|
+
const raw = input.slice(AR_PREFIX.length);
|
|
59
|
+
if (!raw) {
|
|
60
|
+
return grammarInvalid('ar:// ref has no path');
|
|
61
|
+
}
|
|
62
|
+
// Optional `@vN` version suffix, split on the first `@` (mirrors parseArtifactRef).
|
|
63
|
+
let path = raw;
|
|
64
|
+
const atIndex = raw.indexOf('@');
|
|
65
|
+
if (atIndex !== -1) {
|
|
66
|
+
const suffix = raw.slice(atIndex + 1);
|
|
67
|
+
if (!AR_VERSION_SUFFIX_RE.test(suffix)) {
|
|
68
|
+
return grammarInvalid(`ar:// version suffix "@${suffix}" must be @vN`);
|
|
69
|
+
}
|
|
70
|
+
path = raw.slice(0, atIndex);
|
|
71
|
+
}
|
|
72
|
+
const segments = path.split('/');
|
|
73
|
+
if (segments.length !== 5 && segments.length !== 4) {
|
|
74
|
+
return grammarInvalid(`ar:// ref must have 5 (v2) or 4 (legacy) segments, got ${segments.length}`);
|
|
75
|
+
}
|
|
76
|
+
if (segments.some((segment) => segment === '')) {
|
|
77
|
+
return grammarInvalid('ar:// ref has an empty segment');
|
|
78
|
+
}
|
|
79
|
+
return { scheme: 'ar', ref: input };
|
|
80
|
+
}
|
|
81
|
+
function parseRecipe(input) {
|
|
82
|
+
let rest = input.slice(RECIPE_PREFIX.length);
|
|
83
|
+
if (!rest) {
|
|
84
|
+
return grammarInvalid('recipe:// ref has no path');
|
|
85
|
+
}
|
|
86
|
+
// Optional `?tier=` query, passed through verbatim.
|
|
87
|
+
let tier;
|
|
88
|
+
const queryIndex = rest.indexOf('?');
|
|
89
|
+
if (queryIndex !== -1) {
|
|
90
|
+
const query = rest.slice(queryIndex + 1);
|
|
91
|
+
rest = rest.slice(0, queryIndex);
|
|
92
|
+
if (!query.startsWith('tier=') || query.length === 'tier='.length) {
|
|
93
|
+
return grammarInvalid(`recipe:// query must be "?tier=<value>", got "${query}"`);
|
|
94
|
+
}
|
|
95
|
+
tier = query.slice('tier='.length);
|
|
96
|
+
}
|
|
97
|
+
// Optional version suffix `@vN | @N | @head | @latest`.
|
|
98
|
+
let version;
|
|
99
|
+
const atIndex = rest.indexOf('@');
|
|
100
|
+
if (atIndex !== -1) {
|
|
101
|
+
version = rest.slice(atIndex + 1);
|
|
102
|
+
rest = rest.slice(0, atIndex);
|
|
103
|
+
if (!isValidRecipeVersion(version)) {
|
|
104
|
+
return grammarInvalid(`recipe:// version "@${version}" is not @vN, @N, @head, or @latest`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const slashIndex = rest.indexOf('/');
|
|
108
|
+
if (slashIndex === -1) {
|
|
109
|
+
return grammarInvalid('recipe:// ref must be {type}/{name}');
|
|
110
|
+
}
|
|
111
|
+
const type = rest.slice(0, slashIndex);
|
|
112
|
+
const name = rest.slice(slashIndex + 1);
|
|
113
|
+
if (!RECIPE_NAME_CHARSET.test(type)) {
|
|
114
|
+
return grammarInvalid(`recipe:// type "${type}" must match ${RECIPE_NAME_CHARSET}`);
|
|
115
|
+
}
|
|
116
|
+
if (!RECIPE_NAME_CHARSET.test(name)) {
|
|
117
|
+
return grammarInvalid(`recipe:// name "${name}" must match ${RECIPE_NAME_CHARSET}`);
|
|
118
|
+
}
|
|
119
|
+
const result = { scheme: 'recipe', type, name };
|
|
120
|
+
if (version !== undefined) {
|
|
121
|
+
result.version = version;
|
|
122
|
+
}
|
|
123
|
+
if (tier !== undefined) {
|
|
124
|
+
result.tier = tier;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Parse a ref into a discriminated `KernelRef`. Pure and total over the scheme:
|
|
130
|
+
* valid `ar://` / `recipe://` refs parse to their variants, `stash://` /
|
|
131
|
+
* `warden://` / `wf://` parse to `unresolvable`, and anything else throws
|
|
132
|
+
* `ref.grammar.invalid`.
|
|
133
|
+
*/
|
|
134
|
+
export function parse(ref) {
|
|
135
|
+
const input = String(ref);
|
|
136
|
+
if (!input) {
|
|
137
|
+
return grammarInvalid('ref is empty');
|
|
138
|
+
}
|
|
139
|
+
if (input.startsWith(AR_PREFIX)) {
|
|
140
|
+
return parseAr(input);
|
|
141
|
+
}
|
|
142
|
+
if (input.startsWith(RECIPE_PREFIX)) {
|
|
143
|
+
return parseRecipe(input);
|
|
144
|
+
}
|
|
145
|
+
if (input.startsWith('stash://')) {
|
|
146
|
+
return { scheme: 'unresolvable', attemptedScheme: 'stash', ...UNRESOLVABLE.stash };
|
|
147
|
+
}
|
|
148
|
+
if (input.startsWith('warden://')) {
|
|
149
|
+
return { scheme: 'unresolvable', attemptedScheme: 'warden', ...UNRESOLVABLE.warden };
|
|
150
|
+
}
|
|
151
|
+
if (input.startsWith('wf://')) {
|
|
152
|
+
return { scheme: 'unresolvable', attemptedScheme: 'wf', ...UNRESOLVABLE.wf };
|
|
153
|
+
}
|
|
154
|
+
return grammarInvalid(`unsupported scheme in "${input}"`);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Rebuild the route path for a parsed ref. For `recipe://` this is the path-shaped
|
|
158
|
+
* route `{type}/{name}[@{version}][?tier={tier}]`; for `ar://` it is the original
|
|
159
|
+
* string (never decomposed).
|
|
160
|
+
*/
|
|
161
|
+
export function routeFor(ref) {
|
|
162
|
+
switch (ref.scheme) {
|
|
163
|
+
case 'ar':
|
|
164
|
+
return ref.ref;
|
|
165
|
+
case 'recipe': {
|
|
166
|
+
let path = `${ref.type}/${ref.name}`;
|
|
167
|
+
if (ref.version !== undefined) {
|
|
168
|
+
path += `@${ref.version}`;
|
|
169
|
+
}
|
|
170
|
+
if (ref.tier !== undefined) {
|
|
171
|
+
path += `?tier=${ref.tier}`;
|
|
172
|
+
}
|
|
173
|
+
return path;
|
|
174
|
+
}
|
|
175
|
+
case 'unresolvable':
|
|
176
|
+
throw new DominusError(`No route for ${ref.attemptedScheme}:// refs: ${ref.missingContract} (owner: ${ref.owningService})`, 400, { code: 'ref.scheme.unresolvable', category: 'validation' });
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=grammar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../../src/refs/grammar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref transport — the resolver seam that turns a parsed ref into a resolved,
|
|
3
|
+
* service-native receipt.
|
|
4
|
+
*
|
|
5
|
+
* `resolve()` owns transport and owns NO judgment: it asks the owning service
|
|
6
|
+
* for the answer and passes the response back unmodified as a discriminated
|
|
7
|
+
* receipt. It never re-derives tier, scope, or backend selection — those
|
|
8
|
+
* decisions belong to the services (enforced by E1). `parse()` is used only to
|
|
9
|
+
* pick the answering service and reject garbage; for `ar://` the original ref
|
|
10
|
+
* string crosses the wire verbatim and is never decomposed (enforced by E2).
|
|
11
|
+
*
|
|
12
|
+
* `recipe://` transport borrows the `/svc/stash/compose` fall-through contract:
|
|
13
|
+
* probe the Stash lane first, and on a typed `stash.not_found.*` or
|
|
14
|
+
* `stash.forbidden.scope_not_allowed` miss, fall through to the recipe-worker
|
|
15
|
+
* route. Every other `stash.*` error aborts and propagates unmodified — the
|
|
16
|
+
* overlay never reclassifies an upstream failure (the `SharedNeonClient.query()`
|
|
17
|
+
* anti-pattern this seam refuses to repeat). Backend selection is keyed on
|
|
18
|
+
* `err.code`, never on HTTP status.
|
|
19
|
+
*/
|
|
20
|
+
import type { DominusClient } from '../lib/client.js';
|
|
21
|
+
import type { KernelRef } from './grammar.js';
|
|
22
|
+
import type { ResolvedRef } from './types.js';
|
|
23
|
+
/** Call-site options for {@link RefResolver.resolve}. */
|
|
24
|
+
export interface ResolveOptions {
|
|
25
|
+
/** Stash-lane read scope; consumed by the `recipe://` arm (no default). */
|
|
26
|
+
env?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare class RefResolver {
|
|
29
|
+
private client;
|
|
30
|
+
constructor(client: DominusClient);
|
|
31
|
+
/**
|
|
32
|
+
* Parse a ref into its discriminated {@link KernelRef} with no I/O.
|
|
33
|
+
* Delegates to the pure grammar module (`src/refs/grammar.ts`); the
|
|
34
|
+
* resolver owns transport, not grammar.
|
|
35
|
+
*/
|
|
36
|
+
parse(ref: string): KernelRef;
|
|
37
|
+
resolve(ref: string, options?: ResolveOptions): Promise<ResolvedRef>;
|
|
38
|
+
private resolveArtifact;
|
|
39
|
+
private resolveRecipe;
|
|
40
|
+
private resolveRecipeWorker;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The two typed legs that may fall through to the recipe-worker route. Keyed on
|
|
44
|
+
* `err.code`, never HTTP status — a 403-coded `scope_not_allowed` falls through
|
|
45
|
+
* while a 401-coded auth failure aborts. Exported so `RecipesNamespace.get`
|
|
46
|
+
* reuses the same predicate instead of maintaining a second copy.
|
|
47
|
+
*/
|
|
48
|
+
export declare function isFallThrough(err: unknown): boolean;
|
|
49
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/refs/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,cAAc,CAAC;AAEzD,OAAO,KAAK,EAA4B,WAAW,EAA0B,MAAM,YAAY,CAAC;AAEhG,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,qBAAa,WAAW;IACV,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAEzC;;;;OAIG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAIvB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC;YAkBhE,eAAe;YAgBf,aAAa;YA2Cb,mBAAmB;CAclC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAInD"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref transport — the resolver seam that turns a parsed ref into a resolved,
|
|
3
|
+
* service-native receipt.
|
|
4
|
+
*
|
|
5
|
+
* `resolve()` owns transport and owns NO judgment: it asks the owning service
|
|
6
|
+
* for the answer and passes the response back unmodified as a discriminated
|
|
7
|
+
* receipt. It never re-derives tier, scope, or backend selection — those
|
|
8
|
+
* decisions belong to the services (enforced by E1). `parse()` is used only to
|
|
9
|
+
* pick the answering service and reject garbage; for `ar://` the original ref
|
|
10
|
+
* string crosses the wire verbatim and is never decomposed (enforced by E2).
|
|
11
|
+
*
|
|
12
|
+
* `recipe://` transport borrows the `/svc/stash/compose` fall-through contract:
|
|
13
|
+
* probe the Stash lane first, and on a typed `stash.not_found.*` or
|
|
14
|
+
* `stash.forbidden.scope_not_allowed` miss, fall through to the recipe-worker
|
|
15
|
+
* route. Every other `stash.*` error aborts and propagates unmodified — the
|
|
16
|
+
* overlay never reclassifies an upstream failure (the `SharedNeonClient.query()`
|
|
17
|
+
* anti-pattern this seam refuses to repeat). Backend selection is keyed on
|
|
18
|
+
* `err.code`, never on HTTP status.
|
|
19
|
+
*/
|
|
20
|
+
import { DominusError, ValidationError } from '../lib/errors.js';
|
|
21
|
+
import { parse as parseGrammar, routeFor } from './grammar.js';
|
|
22
|
+
export class RefResolver {
|
|
23
|
+
client;
|
|
24
|
+
constructor(client) {
|
|
25
|
+
this.client = client;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse a ref into its discriminated {@link KernelRef} with no I/O.
|
|
29
|
+
* Delegates to the pure grammar module (`src/refs/grammar.ts`); the
|
|
30
|
+
* resolver owns transport, not grammar.
|
|
31
|
+
*/
|
|
32
|
+
parse(ref) {
|
|
33
|
+
return parseGrammar(ref);
|
|
34
|
+
}
|
|
35
|
+
async resolve(ref, options = {}) {
|
|
36
|
+
const parsed = parseGrammar(ref);
|
|
37
|
+
if (parsed.scheme === 'ar') {
|
|
38
|
+
return this.resolveArtifact(parsed.ref);
|
|
39
|
+
}
|
|
40
|
+
if (parsed.scheme === 'unresolvable') {
|
|
41
|
+
throw new DominusError(`No route for ${parsed.attemptedScheme}:// refs: ${parsed.missingContract} (owner: ${parsed.owningService})`, 400, { code: 'ref.scheme.unresolvable', category: 'validation' });
|
|
42
|
+
}
|
|
43
|
+
return this.resolveRecipe(parsed, ref, options);
|
|
44
|
+
}
|
|
45
|
+
async resolveArtifact(ref) {
|
|
46
|
+
const receipt = await this.client.request({
|
|
47
|
+
endpoint: '/api/artifact/v2/retrieve',
|
|
48
|
+
method: 'POST',
|
|
49
|
+
body: { ref },
|
|
50
|
+
useGateway: true,
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
source: 'artifact',
|
|
54
|
+
ref,
|
|
55
|
+
payload: receipt.data ?? '',
|
|
56
|
+
receipt,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async resolveRecipe(parsed, ref, options) {
|
|
60
|
+
const env = options.env;
|
|
61
|
+
if (env === undefined || env === '') {
|
|
62
|
+
throw new ValidationError('recipe:// stash-lane reads require an explicit env', 400, {
|
|
63
|
+
code: 'ref.env.required',
|
|
64
|
+
category: 'validation',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
const version = toStashVersion(parsed.version);
|
|
68
|
+
try {
|
|
69
|
+
const response = await this.client.request({
|
|
70
|
+
endpoint: '/svc/stash/get',
|
|
71
|
+
method: 'POST',
|
|
72
|
+
body: {
|
|
73
|
+
env,
|
|
74
|
+
kind: parsed.type,
|
|
75
|
+
scope: 'self',
|
|
76
|
+
key: parsed.name,
|
|
77
|
+
...(version !== undefined ? { version } : {}),
|
|
78
|
+
},
|
|
79
|
+
useGateway: true,
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
source: 'stash',
|
|
83
|
+
ref,
|
|
84
|
+
payload: response.value,
|
|
85
|
+
receipt: response,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (isFallThrough(err)) {
|
|
90
|
+
return this.resolveRecipeWorker(parsed, ref);
|
|
91
|
+
}
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async resolveRecipeWorker(parsed, ref) {
|
|
96
|
+
const resolved = await this.client.request({
|
|
97
|
+
endpoint: `/api/recipe/recipes/${routeFor(parsed)}`,
|
|
98
|
+
method: 'GET',
|
|
99
|
+
useGateway: true,
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
source: 'recipe-worker',
|
|
103
|
+
ref,
|
|
104
|
+
payload: resolved.body,
|
|
105
|
+
receipt: resolved.metadata,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* The two typed legs that may fall through to the recipe-worker route. Keyed on
|
|
111
|
+
* `err.code`, never HTTP status — a 403-coded `scope_not_allowed` falls through
|
|
112
|
+
* while a 401-coded auth failure aborts. Exported so `RecipesNamespace.get`
|
|
113
|
+
* reuses the same predicate instead of maintaining a second copy.
|
|
114
|
+
*/
|
|
115
|
+
export function isFallThrough(err) {
|
|
116
|
+
if (!(err instanceof DominusError))
|
|
117
|
+
return false;
|
|
118
|
+
const code = err.code ?? '';
|
|
119
|
+
return code.startsWith('stash.not_found.') || code === 'stash.forbidden.scope_not_allowed';
|
|
120
|
+
}
|
|
121
|
+
/** Map a `recipe://` version token to the stash version selector. */
|
|
122
|
+
function toStashVersion(version) {
|
|
123
|
+
if (version === undefined || version === 'head' || version === 'latest') {
|
|
124
|
+
return version;
|
|
125
|
+
}
|
|
126
|
+
const numeric = version.startsWith('v') ? version.slice(1) : version;
|
|
127
|
+
return Number(numeric);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/refs/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref receipt types — the public return contract of the ref resolver seam.
|
|
3
|
+
*
|
|
4
|
+
* `ResolvedRef` is discriminated on `source` (the answering service). Each
|
|
5
|
+
* variant carries that service's own response as its `receipt`, unmodified —
|
|
6
|
+
* provenance is passed through, never normalized, never synthesized. Because
|
|
7
|
+
* `owner` exists on the recipe-worker variant (it is a field of the worker's
|
|
8
|
+
* own `RecipeMetadata`) and does NOT exist on the stash variant, an empty
|
|
9
|
+
* owner (`owner: ''`) is unrepresentable at compile time. E4 proves this.
|
|
10
|
+
*
|
|
11
|
+
* Shared across variants: `ref`, `source`, and `payload` only. No provenance
|
|
12
|
+
* field (tier, scope, owner, backend) is shared across variants.
|
|
13
|
+
*/
|
|
14
|
+
import type { RecipeMetadata } from '../namespaces/recipes.js';
|
|
15
|
+
/** The `/svc/artifact/v2/retrieve` response (artifact-worker V2 retrieve). */
|
|
16
|
+
export interface ArtifactRetrieveResponse {
|
|
17
|
+
resolved_ref: string | null;
|
|
18
|
+
head_ref: string | null;
|
|
19
|
+
snapshot_ref: string | null;
|
|
20
|
+
version: number | null;
|
|
21
|
+
data: string | null;
|
|
22
|
+
content_type: string | null;
|
|
23
|
+
storage_type: 'redis' | 'b2' | null;
|
|
24
|
+
size_bytes: number | null;
|
|
25
|
+
expires_at: string | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The fields `/svc/stash/get` actually returns (stash-worker pointer-text
|
|
29
|
+
* `get`). `scope_resolved` is the worker's own `tierMeta(...)` expansion.
|
|
30
|
+
*/
|
|
31
|
+
export interface StashResolutionReceipt {
|
|
32
|
+
resolved_tier: string;
|
|
33
|
+
source_scope: string;
|
|
34
|
+
scope_resolved: Record<string, unknown>;
|
|
35
|
+
scope_hash: string;
|
|
36
|
+
value_hash: string;
|
|
37
|
+
version: number;
|
|
38
|
+
}
|
|
39
|
+
/** A resolved ref, keyed on the answering service. */
|
|
40
|
+
export type ResolvedRef = {
|
|
41
|
+
source: 'artifact';
|
|
42
|
+
ref: string;
|
|
43
|
+
payload: string;
|
|
44
|
+
receipt: ArtifactRetrieveResponse;
|
|
45
|
+
} | {
|
|
46
|
+
source: 'recipe-worker';
|
|
47
|
+
ref: string;
|
|
48
|
+
payload: string;
|
|
49
|
+
receipt: RecipeMetadata;
|
|
50
|
+
} | {
|
|
51
|
+
source: 'stash';
|
|
52
|
+
ref: string;
|
|
53
|
+
payload: unknown;
|
|
54
|
+
receipt: StashResolutionReceipt;
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/refs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE/D,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,sDAAsD;AACtD,MAAM,MAAM,WAAW,GACnB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,GACvF;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAClF;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ref receipt types — the public return contract of the ref resolver seam.
|
|
3
|
+
*
|
|
4
|
+
* `ResolvedRef` is discriminated on `source` (the answering service). Each
|
|
5
|
+
* variant carries that service's own response as its `receipt`, unmodified —
|
|
6
|
+
* provenance is passed through, never normalized, never synthesized. Because
|
|
7
|
+
* `owner` exists on the recipe-worker variant (it is a field of the worker's
|
|
8
|
+
* own `RecipeMetadata`) and does NOT exist on the stash variant, an empty
|
|
9
|
+
* owner (`owner: ''`) is unrepresentable at compile time. E4 proves this.
|
|
10
|
+
*
|
|
11
|
+
* Shared across variants: `ref`, `source`, and `payload` only. No provenance
|
|
12
|
+
* field (tier, scope, owner, backend) is shared across variants.
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/refs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# 00 Reading Order
|
|
2
|
-
|
|
3
|
-
Snapshot: 2026-06-27-0849-sdk-orient. Source-backed at SDK v6.6.0, branch
|
|
4
|
-
`production`. Code is authority; this guide is a map.
|
|
5
|
-
|
|
6
|
-
## Read These First (docs)
|
|
7
|
-
|
|
8
|
-
1. This pack, in INDEX order.
|
|
9
|
-
2. `docs/architecture.md` — request lifecycle, layering, Two-Layer Storage Rule.
|
|
10
|
-
3. `docs/routes-services.md` — service/endpoint matrix and route-prefix mapping.
|
|
11
|
-
4. `docs/usage-reference.md` — exhaustive per-command reference (large; grep it,
|
|
12
|
-
do not read top-to-bottom).
|
|
13
|
-
5. `CLAUDE.md` — repo conventions and the public-API change checklist.
|
|
14
|
-
|
|
15
|
-
## Open Source Only For Specific Tasks
|
|
16
|
-
|
|
17
|
-
- Changing a namespace command → the one file in `src/namespaces/<name>.ts`.
|
|
18
|
-
- Transport / auth / retries / streaming / binary → `src/lib/client.ts`.
|
|
19
|
-
- New public type or root shortcut → `src/index.ts`.
|
|
20
|
-
- Env / gateway resolution → `src/lib/config.ts`.
|
|
21
|
-
- Error classification → `src/lib/errors.ts`.
|
|
22
|
-
|
|
23
|
-
## Stale / Dangerous
|
|
24
|
-
|
|
25
|
-
- `docs/architecture.md` §10 and `CLAUDE.md` Validation note previously said "no
|
|
26
|
-
committed automated tests". STALE — `tests/` has 24 files run by `npm test`.
|
|
27
|
-
Corrected in this pass; if you see the old claim re-appear, fix it.
|
|
28
|
-
- `dist/` is generated build output (gitignored). Never use it for design
|
|
29
|
-
decisions or treat it as source.
|
|
30
|
-
|
|
31
|
-
## Related Surfaces
|
|
32
|
-
|
|
33
|
-
- Janitor cleanup audit:
|
|
34
|
-
`docs/janitor/2026-06-27-0849-sdk-orient-cleanup-audit.md`.
|
|
35
|
-
- No `docs/atlas/` exists yet; run `kyle-atlas` if truth scatters.
|
|
1
|
+
# 00 Reading Order
|
|
2
|
+
|
|
3
|
+
Snapshot: 2026-06-27-0849-sdk-orient. Source-backed at SDK v6.6.0, branch
|
|
4
|
+
`production`. Code is authority; this guide is a map.
|
|
5
|
+
|
|
6
|
+
## Read These First (docs)
|
|
7
|
+
|
|
8
|
+
1. This pack, in INDEX order.
|
|
9
|
+
2. `docs/architecture.md` — request lifecycle, layering, Two-Layer Storage Rule.
|
|
10
|
+
3. `docs/routes-services.md` — service/endpoint matrix and route-prefix mapping.
|
|
11
|
+
4. `docs/usage-reference.md` — exhaustive per-command reference (large; grep it,
|
|
12
|
+
do not read top-to-bottom).
|
|
13
|
+
5. `CLAUDE.md` — repo conventions and the public-API change checklist.
|
|
14
|
+
|
|
15
|
+
## Open Source Only For Specific Tasks
|
|
16
|
+
|
|
17
|
+
- Changing a namespace command → the one file in `src/namespaces/<name>.ts`.
|
|
18
|
+
- Transport / auth / retries / streaming / binary → `src/lib/client.ts`.
|
|
19
|
+
- New public type or root shortcut → `src/index.ts`.
|
|
20
|
+
- Env / gateway resolution → `src/lib/config.ts`.
|
|
21
|
+
- Error classification → `src/lib/errors.ts`.
|
|
22
|
+
|
|
23
|
+
## Stale / Dangerous
|
|
24
|
+
|
|
25
|
+
- `docs/architecture.md` §10 and `CLAUDE.md` Validation note previously said "no
|
|
26
|
+
committed automated tests". STALE — `tests/` has 24 files run by `npm test`.
|
|
27
|
+
Corrected in this pass; if you see the old claim re-appear, fix it.
|
|
28
|
+
- `dist/` is generated build output (gitignored). Never use it for design
|
|
29
|
+
decisions or treat it as source.
|
|
30
|
+
|
|
31
|
+
## Related Surfaces
|
|
32
|
+
|
|
33
|
+
- Janitor cleanup audit:
|
|
34
|
+
`docs/janitor/2026-06-27-0849-sdk-orient-cleanup-audit.md`.
|
|
35
|
+
- No `docs/atlas/` exists yet; run `kyle-atlas` if truth scatters.
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
# 01 Purpose And Boundaries
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
`dominus-sdk-nodejs` is the TypeScript/ESM client SDK for the Dominus
|
|
6
|
-
gateway-first platform (`package.json` `description`). It exposes a singleton
|
|
7
|
-
`dominus` (`src/index.ts`) with namespace-based APIs for auth, data, storage,
|
|
8
|
-
AI/runtime, workflow execution, jobs, and platform administration. Application
|
|
9
|
-
code uses this SDK rather than calling gateway routes directly.
|
|
10
|
-
|
|
11
|
-
## What This Repo Owns
|
|
12
|
-
|
|
13
|
-
- The public client surface: namespaces (`src/namespaces/*.ts`), root shortcuts,
|
|
14
|
-
and exported types/utilities (`src/index.ts`).
|
|
15
|
-
- The request/transport contract: base64 wire protocol, JWT mint+cache, retries,
|
|
16
|
-
circuit breaker, SSE streaming, binary upload/download (`src/lib/client.ts`).
|
|
17
|
-
- Ergonomic parameter normalization and the mapping from SDK calls to `/api/*`
|
|
18
|
-
routes that the gateway transforms to `/svc/*`.
|
|
19
|
-
|
|
20
|
-
## What It Does Not Own
|
|
21
|
-
|
|
22
|
-
- Backend behavior or route definitions — those live in the individual Dominus
|
|
23
|
-
workers (gateway, guardian, authority, workflow-manager, agent-runtime, etc.).
|
|
24
|
-
This SDK only describes how to call them.
|
|
25
|
-
- Kernel contracts (identity families, error envelope, deployment lanes). It
|
|
26
|
-
must conform to them, not define them.
|
|
27
|
-
|
|
28
|
-
## Dominus/CareBridge Boundary
|
|
29
|
-
|
|
30
|
-
This is a Dominus platform repo (`dominus_active/`). It is product-agnostic: it
|
|
31
|
-
carries the platform client, not CareBridge product logic. Per workspace policy,
|
|
32
|
-
project↔gateway calls use this SDK with project identity; never forward user or
|
|
33
|
-
machine JWTs to admin-only planes.
|
|
34
|
-
|
|
35
|
-
## Runtime / Deployment Class
|
|
36
|
-
|
|
37
|
-
- Published npm library (`name: dominus-sdk-nodejs`), single export entry
|
|
38
|
-
(`dist/index.js` / `dist/index.d.ts`); no subpath exports.
|
|
39
|
-
- ESM only (`"type": "module"`), Node `>=18` (`engines`).
|
|
40
|
-
- Released by pushing to the `production` branch (npm publish). Per workspace
|
|
41
|
-
convention this repo's production branch is `production`, NOT
|
|
42
|
-
`dominus-production`.
|
|
43
|
-
|
|
44
|
-
## PHI / Secrets / Safety
|
|
45
|
-
|
|
46
|
-
- Service auth is a PSK in `DOMINUS_TOKEN`, exchanged for a short-lived JWT.
|
|
47
|
-
- Never write PHI, secrets, tokens, cookies, or raw response bodies into these
|
|
48
|
-
docs or into logs.
|
|
1
|
+
# 01 Purpose And Boundaries
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
`dominus-sdk-nodejs` is the TypeScript/ESM client SDK for the Dominus
|
|
6
|
+
gateway-first platform (`package.json` `description`). It exposes a singleton
|
|
7
|
+
`dominus` (`src/index.ts`) with namespace-based APIs for auth, data, storage,
|
|
8
|
+
AI/runtime, workflow execution, jobs, and platform administration. Application
|
|
9
|
+
code uses this SDK rather than calling gateway routes directly.
|
|
10
|
+
|
|
11
|
+
## What This Repo Owns
|
|
12
|
+
|
|
13
|
+
- The public client surface: namespaces (`src/namespaces/*.ts`), root shortcuts,
|
|
14
|
+
and exported types/utilities (`src/index.ts`).
|
|
15
|
+
- The request/transport contract: base64 wire protocol, JWT mint+cache, retries,
|
|
16
|
+
circuit breaker, SSE streaming, binary upload/download (`src/lib/client.ts`).
|
|
17
|
+
- Ergonomic parameter normalization and the mapping from SDK calls to `/api/*`
|
|
18
|
+
routes that the gateway transforms to `/svc/*`.
|
|
19
|
+
|
|
20
|
+
## What It Does Not Own
|
|
21
|
+
|
|
22
|
+
- Backend behavior or route definitions — those live in the individual Dominus
|
|
23
|
+
workers (gateway, guardian, authority, workflow-manager, agent-runtime, etc.).
|
|
24
|
+
This SDK only describes how to call them.
|
|
25
|
+
- Kernel contracts (identity families, error envelope, deployment lanes). It
|
|
26
|
+
must conform to them, not define them.
|
|
27
|
+
|
|
28
|
+
## Dominus/CareBridge Boundary
|
|
29
|
+
|
|
30
|
+
This is a Dominus platform repo (`dominus_active/`). It is product-agnostic: it
|
|
31
|
+
carries the platform client, not CareBridge product logic. Per workspace policy,
|
|
32
|
+
project↔gateway calls use this SDK with project identity; never forward user or
|
|
33
|
+
machine JWTs to admin-only planes.
|
|
34
|
+
|
|
35
|
+
## Runtime / Deployment Class
|
|
36
|
+
|
|
37
|
+
- Published npm library (`name: dominus-sdk-nodejs`), single export entry
|
|
38
|
+
(`dist/index.js` / `dist/index.d.ts`); no subpath exports.
|
|
39
|
+
- ESM only (`"type": "module"`), Node `>=18` (`engines`).
|
|
40
|
+
- Released by pushing to the `production` branch (npm publish). Per workspace
|
|
41
|
+
convention this repo's production branch is `production`, NOT
|
|
42
|
+
`dominus-production`.
|
|
43
|
+
|
|
44
|
+
## PHI / Secrets / Safety
|
|
45
|
+
|
|
46
|
+
- Service auth is a PSK in `DOMINUS_TOKEN`, exchanged for a short-lived JWT.
|
|
47
|
+
- Never write PHI, secrets, tokens, cookies, or raw response bodies into these
|
|
48
|
+
docs or into logs.
|