@dharma-ai-labs/agent-fabric 0.2.190 → 0.2.192
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/AGENT_FABRIC_ONBOARDING.md +7 -3
- package/dist/cliVersionContract.test.d.ts +2 -0
- package/dist/cliVersionContract.test.d.ts.map +1 -0
- package/dist/cliVersionContract.test.js +17 -0
- package/dist/cliVersionContract.test.js.map +1 -0
- package/dist/codexSetupLaunchReservation.d.ts +12 -0
- package/dist/codexSetupLaunchReservation.d.ts.map +1 -0
- package/dist/codexSetupLaunchReservation.js +76 -0
- package/dist/codexSetupLaunchReservation.js.map +1 -0
- package/dist/codexSetupLaunchReservation.test.d.ts +2 -0
- package/dist/codexSetupLaunchReservation.test.d.ts.map +1 -0
- package/dist/codexSetupLaunchReservation.test.js +168 -0
- package/dist/codexSetupLaunchReservation.test.js.map +1 -0
- package/dist/codexSetupOwnedConnection.d.ts +4 -1
- package/dist/codexSetupOwnedConnection.d.ts.map +1 -1
- package/dist/codexSetupOwnedConnection.js +16 -3
- package/dist/codexSetupOwnedConnection.js.map +1 -1
- package/dist/codexSetupOwnedConnection.test.js +14 -0
- package/dist/codexSetupOwnedConnection.test.js.map +1 -1
- package/dist/codexSetupPortalIngress.test.d.ts +2 -0
- package/dist/codexSetupPortalIngress.test.d.ts.map +1 -0
- package/dist/codexSetupPortalIngress.test.js +383 -0
- package/dist/codexSetupPortalIngress.test.js.map +1 -0
- package/dist/codexSetupPortalPreparation.d.ts +32 -0
- package/dist/codexSetupPortalPreparation.d.ts.map +1 -0
- package/dist/codexSetupPortalPreparation.js +131 -0
- package/dist/codexSetupPortalPreparation.js.map +1 -0
- package/dist/codexSetupPortalPreparation.test.d.ts +2 -0
- package/dist/codexSetupPortalPreparation.test.d.ts.map +1 -0
- package/dist/codexSetupPortalPreparation.test.js +173 -0
- package/dist/codexSetupPortalPreparation.test.js.map +1 -0
- package/dist/codexSetupPortalPrompt.test.d.ts +2 -0
- package/dist/codexSetupPortalPrompt.test.d.ts.map +1 -0
- package/dist/codexSetupPortalPrompt.test.js +141 -0
- package/dist/codexSetupPortalPrompt.test.js.map +1 -0
- package/dist/codexSetupPortalPromptDigest.d.ts +3 -0
- package/dist/codexSetupPortalPromptDigest.d.ts.map +1 -0
- package/dist/codexSetupPortalPromptDigest.js +18 -0
- package/dist/codexSetupPortalPromptDigest.js.map +1 -0
- package/dist/codexSetupPortalPromptDigest.test.d.ts +2 -0
- package/dist/codexSetupPortalPromptDigest.test.d.ts.map +1 -0
- package/dist/codexSetupPortalPromptDigest.test.js +23 -0
- package/dist/codexSetupPortalPromptDigest.test.js.map +1 -0
- package/dist/codexSetupPublicStdin.d.ts +6 -0
- package/dist/codexSetupPublicStdin.d.ts.map +1 -0
- package/dist/codexSetupPublicStdin.js +36 -0
- package/dist/codexSetupPublicStdin.js.map +1 -0
- package/dist/codexSetupPublicStdin.test.d.ts +2 -0
- package/dist/codexSetupPublicStdin.test.d.ts.map +1 -0
- package/dist/codexSetupPublicStdin.test.js +40 -0
- package/dist/codexSetupPublicStdin.test.js.map +1 -0
- package/dist/codexSetupUserPrompt.d.ts +2 -0
- package/dist/codexSetupUserPrompt.d.ts.map +1 -1
- package/dist/codexSetupUserPrompt.js +13 -7
- package/dist/codexSetupUserPrompt.js.map +1 -1
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +197 -4
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +4 -1
- package/dist/index.test.js.map +1 -1
- package/dist/onboardingContract.test.js +15 -1
- package/dist/onboardingContract.test.js.map +1 -1
- package/dist/repositorySourceCapture.test.js +15 -0
- package/dist/repositorySourceCapture.test.js.map +1 -1
- package/dist/schemas/setup-claim-request.schema.json +10 -0
- package/dist/schemas/setup-host-preparation-v2.schema.json +171 -0
- package/dist/schemas/setup-host-preparation.schema.json +51 -0
- package/dist/schemas/setup-launch-reservation.schema.json +29 -0
- package/dist/usage.js +1 -1
- package/dist/usage.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { canonicalize } from '@dharma-ai-labs/agent-fabric-contracts';
|
|
4
|
+
import test from 'node:test';
|
|
5
|
+
import { requestCodexSetupHostPreparation } from './codexSetupPortalPreparation.js';
|
|
6
|
+
const now = Date.parse('2030-01-01T00:00:00.000Z');
|
|
7
|
+
const reference = '11111111-1111-4111-8111-111111111111';
|
|
8
|
+
const membership = '22222222-2222-4222-8222-222222222222';
|
|
9
|
+
const binding = { recipientEmail: 'synthetic@example.test', repositoryRemoteUrl: 'https://github.com/example/synthetic.git' };
|
|
10
|
+
const fingerprint = `sha256:${'a'.repeat(64)}`;
|
|
11
|
+
const context = { origin: 'https://www.dharma-ai.io', organizationId: 'org_fixture',
|
|
12
|
+
setupReference: reference, recipientMembershipId: membership, repositoryFingerprint: fingerprint,
|
|
13
|
+
policyRevision: 'policy-v1', scopeDigest: `sha256:${'b'.repeat(64)}`, contractDigest: `sha256:${'c'.repeat(64)}` };
|
|
14
|
+
const contextHash = (value) => createHash('sha256').update('dharma.setup-host-context/v1\0').update(canonicalize({
|
|
15
|
+
cliVersion: value.cliVersion, expiresAt: value.expiresAt, binding: value.binding, context: value.context
|
|
16
|
+
})).digest('hex');
|
|
17
|
+
const originalPin = contextHash({ cliVersion: '0.2.190', expiresAt: '2030-01-01T00:15:00.000Z', binding, context });
|
|
18
|
+
const prompt = '# Dharma Agent Fabric \u2014 one-prompt source setup\n'
|
|
19
|
+
+ `Recipient: ${binding.recipientEmail}. Organization: org_fixture.\n`
|
|
20
|
+
+ `Selected repository: ${binding.repositoryRemoteUrl}. Fingerprint: ${fingerprint}.\n`
|
|
21
|
+
+ `Public setup reference: ${reference}. Fixed expiry: 2030-01-01T00:15:00.000Z.\n`
|
|
22
|
+
+ `Preparation context SHA256: ${originalPin}.\n`;
|
|
23
|
+
function fixture() {
|
|
24
|
+
let calls = 0;
|
|
25
|
+
const response = { schema: 'dharma.setup-host-preparation/v1', ok: true, effects: false,
|
|
26
|
+
grantRedeemed: false, approvalRequired: true, sourcePolicyRevalidated: true,
|
|
27
|
+
preparedAt: new Date(now).toISOString(), expiresAt: '2030-01-01T00:15:00.000Z',
|
|
28
|
+
promptSha256: createHash('sha256').update(prompt).digest('hex'), cliVersion: '0.2.190',
|
|
29
|
+
binding: { ...binding }, context: { ...context },
|
|
30
|
+
integrity: { algorithm: 'sha256', kind: 'portal-context', authenticity: 'same-origin-https', contextSha256: originalPin } };
|
|
31
|
+
const input = { origin: response.context.origin, organizationId: 'org_fixture', setupReference: reference,
|
|
32
|
+
cliVersion: '0.2.190', initialUserPrompt: prompt, signal: new AbortController().signal, now: () => now,
|
|
33
|
+
fetcher: (async (url, options) => {
|
|
34
|
+
calls++;
|
|
35
|
+
assert.equal(String(url), 'https://www.dharma-ai.io/api/v1/agent-fabric/bootstrap/setup-claim');
|
|
36
|
+
assert.equal(options?.redirect, 'error');
|
|
37
|
+
assert.deepEqual(JSON.parse(String(options?.body)), { action: 'prepare_host', organizationId: 'org_fixture',
|
|
38
|
+
setupReference: reference, promptSha256: createHash('sha256').update(prompt).digest('hex') });
|
|
39
|
+
assert.equal(options?.credentials, 'omit');
|
|
40
|
+
return new Response(JSON.stringify(response), { headers: { 'content-type': 'application/json' } });
|
|
41
|
+
}) };
|
|
42
|
+
return { response, input, get calls() { return calls; } };
|
|
43
|
+
}
|
|
44
|
+
test('public preparation obtains independent server binding without invoking a provider or enrollment', async () => {
|
|
45
|
+
const f = fixture();
|
|
46
|
+
const result = await requestCodexSetupHostPreparation(f.input);
|
|
47
|
+
assert.equal(f.calls, 1);
|
|
48
|
+
assert.deepEqual(result.binding, binding);
|
|
49
|
+
assert.equal(result.initialUserPrompt, prompt);
|
|
50
|
+
assert.equal(result.effects, false);
|
|
51
|
+
assert.equal(result.portalContextSha256, originalPin);
|
|
52
|
+
});
|
|
53
|
+
test('portal-pinned context is canonical across JSON object key order', async () => {
|
|
54
|
+
const f = fixture();
|
|
55
|
+
f.response.context = Object.fromEntries(Object.entries(f.response.context).reverse());
|
|
56
|
+
assert.equal((await requestCodexSetupHostPreparation(f.input)).portalContextSha256, originalPin);
|
|
57
|
+
});
|
|
58
|
+
test('a replayed intact context cannot extend its fixed expiry', async () => {
|
|
59
|
+
const f = fixture();
|
|
60
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, now: () => now + 900001 }));
|
|
61
|
+
assert.equal(f.calls, 1);
|
|
62
|
+
});
|
|
63
|
+
test('credential-shaped prose is rejected before any network admission', async () => {
|
|
64
|
+
const f = fixture();
|
|
65
|
+
const canary = ['dhab', 'synthetic', 'not-a-real-grant'].join('_');
|
|
66
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, initialUserPrompt: prompt + canary }));
|
|
67
|
+
assert.equal(f.calls, 0);
|
|
68
|
+
});
|
|
69
|
+
for (const field of ['recipientMembershipId', 'policyRevision', 'scopeDigest', 'contractDigest']) {
|
|
70
|
+
test(`recomputed response integrity cannot substitute the original portal-pinned ${field}`, async () => {
|
|
71
|
+
const f = fixture();
|
|
72
|
+
if (field === 'recipientMembershipId')
|
|
73
|
+
f.response.context[field] = reference;
|
|
74
|
+
else if (field === 'policyRevision')
|
|
75
|
+
f.response.context[field] = 'foreign-policy';
|
|
76
|
+
else
|
|
77
|
+
f.response.context[field] = 'sha256:' + 'f'.repeat(64);
|
|
78
|
+
f.response.integrity.contextSha256 = contextHash(f.response);
|
|
79
|
+
await assert.rejects(requestCodexSetupHostPreparation(f.input), /^Error: codex_setup_portal_preparation_unavailable$/);
|
|
80
|
+
assert.equal(f.calls, 1);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
for (const reason of ['missing', 'duplicate']) {
|
|
84
|
+
test(`a ${reason} original portal context pin is rejected before fetch`, async () => {
|
|
85
|
+
const f = fixture();
|
|
86
|
+
const value = reason === 'missing' ? prompt.replace(`Preparation context SHA256: ${originalPin}.\n`, '')
|
|
87
|
+
: prompt + `Preparation context SHA256: ${originalPin}.\n`;
|
|
88
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, initialUserPrompt: value }));
|
|
89
|
+
assert.equal(f.calls, 0);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
test('bounded server clock lead waits without weakening issued-at or expiry validation', async () => {
|
|
93
|
+
const f = fixture();
|
|
94
|
+
let localNow = now, waited = 0;
|
|
95
|
+
f.response.preparedAt = new Date(now + 2208).toISOString();
|
|
96
|
+
const result = await requestCodexSetupHostPreparation({ ...f.input, now: () => localNow,
|
|
97
|
+
...{ sleep: async (ms) => { waited++; assert.equal(ms, 2208); localNow += ms; } } });
|
|
98
|
+
assert.equal(waited, 1);
|
|
99
|
+
assert.equal(result.intent.issuedAt, f.response.preparedAt);
|
|
100
|
+
assert.equal(f.calls, 1);
|
|
101
|
+
});
|
|
102
|
+
test('excessive server clock lead is rejected without sleeping or provider effects', async () => {
|
|
103
|
+
const f = fixture();
|
|
104
|
+
let waits = 0;
|
|
105
|
+
f.response.preparedAt = new Date(now + 5001).toISOString();
|
|
106
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input,
|
|
107
|
+
...{ sleep: async () => { waits++; } } }));
|
|
108
|
+
assert.equal(waits, 0);
|
|
109
|
+
assert.equal(f.calls, 1);
|
|
110
|
+
});
|
|
111
|
+
test('clock wait cancellation cannot authorize a future preparation', async () => {
|
|
112
|
+
const f = fixture(), control = new AbortController();
|
|
113
|
+
f.response.preparedAt = new Date(now + 1000).toISOString();
|
|
114
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, signal: control.signal,
|
|
115
|
+
...{ sleep: async () => { control.abort(); } } }));
|
|
116
|
+
});
|
|
117
|
+
test('clipboard CRLF uses the same public digest while preserving actual native message bytes', async () => {
|
|
118
|
+
const f = fixture(), original = prompt.replace(/\n/g, '\r\n');
|
|
119
|
+
const result = await requestCodexSetupHostPreparation({ ...f.input, initialUserPrompt: original });
|
|
120
|
+
assert.equal(result.initialUserPrompt, original);
|
|
121
|
+
assert.equal(result.initialUserPromptSha256, createHash('sha256').update(original).digest('hex'));
|
|
122
|
+
assert.equal(result.promptSha256, createHash('sha256').update(prompt).digest('hex'));
|
|
123
|
+
});
|
|
124
|
+
for (const cause of ['origin', 'organization', 'reference', 'version', 'prompt-hash', 'recipient', 'repository', 'expired', 'effects', 'unknown']) {
|
|
125
|
+
test(`public preparation rejects ${cause} instead of accepting model-supplied binding`, async () => {
|
|
126
|
+
const f = fixture();
|
|
127
|
+
if (cause === 'origin')
|
|
128
|
+
f.response.context.origin = 'https://foreign.example';
|
|
129
|
+
if (cause === 'organization')
|
|
130
|
+
f.response.context.organizationId = 'org_foreign';
|
|
131
|
+
if (cause === 'reference')
|
|
132
|
+
f.response.context.setupReference = membership;
|
|
133
|
+
if (cause === 'version')
|
|
134
|
+
f.response.cliVersion = '0.2.191';
|
|
135
|
+
if (cause === 'prompt-hash')
|
|
136
|
+
f.response.promptSha256 = 'e'.repeat(64);
|
|
137
|
+
if (cause === 'recipient')
|
|
138
|
+
f.response.binding.recipientEmail = 'other@example.test';
|
|
139
|
+
if (cause === 'repository')
|
|
140
|
+
f.response.binding.repositoryRemoteUrl = 'https://github.com/other/source.git';
|
|
141
|
+
if (cause === 'expired')
|
|
142
|
+
f.response.expiresAt = new Date(now).toISOString();
|
|
143
|
+
if (cause === 'effects')
|
|
144
|
+
f.response.effects = true;
|
|
145
|
+
if (cause === 'unknown')
|
|
146
|
+
f.response.privateField = 'PRIVATE_CANARY';
|
|
147
|
+
await assert.rejects(requestCodexSetupHostPreparation(f.input));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
test('a cancelled preparation makes no network request', async () => {
|
|
151
|
+
const f = fixture();
|
|
152
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, signal: AbortSignal.abort() }));
|
|
153
|
+
assert.equal(f.calls, 0);
|
|
154
|
+
});
|
|
155
|
+
for (const cause of ['http-error', 'invalid-json', 'oversized', 'foreign-redirect', 'vendor-error']) {
|
|
156
|
+
test(`transport ${cause} is bounded, not retried and never reflects a response or vendor exception`, async () => {
|
|
157
|
+
const f = fixture();
|
|
158
|
+
let calls = 0;
|
|
159
|
+
const fetcher = (async () => {
|
|
160
|
+
calls++;
|
|
161
|
+
if (cause === 'vendor-error')
|
|
162
|
+
throw Error('PRIVATE_VENDOR_EXCEPTION');
|
|
163
|
+
if (cause === 'http-error')
|
|
164
|
+
return new Response('PRIVATE_RESPONSE', { status: 403 });
|
|
165
|
+
if (cause === 'foreign-redirect')
|
|
166
|
+
return new Response('', { status: 302, headers: { location: 'https://foreign.example' } });
|
|
167
|
+
return new Response(cause === 'invalid-json' ? 'PRIVATE_INVALID_RESPONSE' : 'x'.repeat(65537), { headers: { 'content-type': 'application/json' } });
|
|
168
|
+
});
|
|
169
|
+
await assert.rejects(requestCodexSetupHostPreparation({ ...f.input, fetcher }), error => error instanceof Error && error.message === 'codex_setup_portal_preparation_unavailable');
|
|
170
|
+
assert.equal(calls, 1);
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=codexSetupPortalPreparation.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPreparation.test.js","sourceRoot":"","sources":["../src/codexSetupPortalPreparation.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPrompt.test.d.ts","sourceRoot":"","sources":["../src/codexSetupPortalPrompt.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { createServer } from 'node:http';
|
|
4
|
+
import { once } from 'node:events';
|
|
5
|
+
import { canonicalize } from '@dharma-ai-labs/agent-fabric-contracts';
|
|
6
|
+
import test from 'node:test';
|
|
7
|
+
import { requestCodexSetupHostPreparation } from './codexSetupPortalPreparation.js';
|
|
8
|
+
const now = Date.parse('2030-01-01T00:00:00.000Z'), expiresAt = '2030-01-01T00:15:00.000Z';
|
|
9
|
+
const context = { origin: 'https://www.dharma-ai.io', organizationId: 'org_fixture',
|
|
10
|
+
setupReference: '11111111-1111-4111-8111-111111111111', recipientMembershipId: '22222222-2222-4222-8222-222222222222',
|
|
11
|
+
repositoryFingerprint: 'sha256:' + 'a'.repeat(64), policyRevision: 'policy-v1', scopeDigest: 'sha256:' + 'b'.repeat(64), contractDigest: 'sha256:' + 'c'.repeat(64) };
|
|
12
|
+
const binding = { recipientEmail: 'synthetic@example.test', repositoryRemoteUrl: 'https://github.com/example/synthetic.git' };
|
|
13
|
+
const pin = createHash('sha256').update('dharma.setup-host-context/v1\0').update(canonicalize({ cliVersion: '0.2.192', expiresAt, binding, context })).digest('hex');
|
|
14
|
+
const template = '# Dharma Agent Fabric \u2014 one-prompt source setup\n'
|
|
15
|
+
+ `Recipient: ${binding.recipientEmail}. Organization: ${context.organizationId}.\n`
|
|
16
|
+
+ `Selected repository: ${binding.repositoryRemoteUrl}. Fingerprint: ${context.repositoryFingerprint}.\n`
|
|
17
|
+
+ `Public setup reference: ${context.setupReference}. Fixed expiry: ${expiresAt}.\n`
|
|
18
|
+
+ `Preparation context SHA256: ${pin}.\n`
|
|
19
|
+
+ 'dharma setup codex --portal-prompt-sha256 ' + '0'.repeat(64) + '\n';
|
|
20
|
+
const portalDigest = createHash('sha256').update(template).digest('hex');
|
|
21
|
+
const prompt = template.replace('--portal-prompt-sha256 ' + '0'.repeat(64), '--portal-prompt-sha256 ' + portalDigest);
|
|
22
|
+
function fixture() {
|
|
23
|
+
let calls = 0;
|
|
24
|
+
const response = { schema: 'dharma.setup-host-preparation/v2', ok: true, effects: false, grantRedeemed: false,
|
|
25
|
+
approvalRequired: true, sourcePolicyRevalidated: true, preparedAt: new Date(now).toISOString(), expiresAt,
|
|
26
|
+
promptSha256: createHash('sha256').update(prompt).digest('hex'), cliVersion: '0.2.192', binding: { ...binding }, context: { ...context },
|
|
27
|
+
integrity: { algorithm: 'sha256', kind: 'portal-context', authenticity: 'same-origin-https', contextSha256: pin },
|
|
28
|
+
publicPrompt: prompt, promptSource: 'portal_setup_prompt', portalPromptSha256: portalDigest };
|
|
29
|
+
const input = { origin: context.origin, organizationId: context.organizationId, setupReference: context.setupReference,
|
|
30
|
+
cliVersion: '0.2.192', portalContextSha256: pin, portalPromptSha256: portalDigest,
|
|
31
|
+
signal: new AbortController().signal, now: () => now,
|
|
32
|
+
fetcher: async (url, options) => {
|
|
33
|
+
calls++;
|
|
34
|
+
assert.equal(String(url), context.origin + '/api/v1/agent-fabric/bootstrap/setup-claim');
|
|
35
|
+
assert.equal(options.redirect, 'error');
|
|
36
|
+
assert.equal(options.credentials, 'omit');
|
|
37
|
+
assert.deepEqual(JSON.parse(options.body), { action: 'prepare_host', organizationId: context.organizationId,
|
|
38
|
+
setupReference: context.setupReference, promptSource: 'portal_setup_prompt', contextSha256: pin, portalPromptSha256: portalDigest });
|
|
39
|
+
return new Response(JSON.stringify(response), { headers: { 'content-type': 'application/json' } });
|
|
40
|
+
} };
|
|
41
|
+
return { input, response, get calls() { return calls; } };
|
|
42
|
+
}
|
|
43
|
+
test('canonical portal input is fetched without reading stdin or private native history', async () => {
|
|
44
|
+
const f = fixture(), value = await requestCodexSetupHostPreparation(f.input);
|
|
45
|
+
assert.equal(f.calls, 1);
|
|
46
|
+
assert.equal(value.initialUserPrompt, prompt);
|
|
47
|
+
assert.equal(value.promptProvenance, 'verified_portal_prompt');
|
|
48
|
+
assert.equal(value.nativeOriginalUserPromptAttested, false);
|
|
49
|
+
assert.equal(value.portalContextSha256, pin);
|
|
50
|
+
assert.equal(value.effects, false);
|
|
51
|
+
assert.equal(value.grantRedeemed, false);
|
|
52
|
+
});
|
|
53
|
+
test('the actual client parses canonical portal input over a real HTTP fixture', async () => {
|
|
54
|
+
const f = fixture();
|
|
55
|
+
let requests = 0;
|
|
56
|
+
const server = createServer(async (incoming, outgoing) => {
|
|
57
|
+
const chunks = [];
|
|
58
|
+
for await (const chunk of incoming)
|
|
59
|
+
chunks.push(Buffer.from(chunk));
|
|
60
|
+
const body = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
61
|
+
requests++;
|
|
62
|
+
assert.equal(body.promptSource, 'portal_setup_prompt');
|
|
63
|
+
assert.equal(body.contextSha256, pin);
|
|
64
|
+
assert.equal(body.portalPromptSha256, portalDigest);
|
|
65
|
+
assert.equal('promptSha256' in body, false);
|
|
66
|
+
outgoing.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
67
|
+
outgoing.end(JSON.stringify(f.response));
|
|
68
|
+
});
|
|
69
|
+
try {
|
|
70
|
+
server.listen(0, '127.0.0.1');
|
|
71
|
+
await once(server, 'listening');
|
|
72
|
+
const address = server.address();
|
|
73
|
+
assert.ok(address && typeof address !== 'string');
|
|
74
|
+
// Inject only a loopback test transport. Production still requires HTTPS;
|
|
75
|
+
// this test qualifies serialization/parser compatibility, not TLS trust.
|
|
76
|
+
const result = await requestCodexSetupHostPreparation({ ...f.input, fetcher: async (url, options) => {
|
|
77
|
+
assert.equal(String(url), context.origin + '/api/v1/agent-fabric/bootstrap/setup-claim');
|
|
78
|
+
return fetch(`http://127.0.0.1:${address.port}/api/v1/agent-fabric/bootstrap/setup-claim`, options);
|
|
79
|
+
} });
|
|
80
|
+
assert.equal(result.initialUserPrompt, prompt);
|
|
81
|
+
assert.equal(result.promptProvenance, 'verified_portal_prompt');
|
|
82
|
+
assert.equal(result.nativeOriginalUserPromptAttested, false);
|
|
83
|
+
assert.equal(requests, 1);
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
server.closeAllConnections();
|
|
87
|
+
if (server.listening)
|
|
88
|
+
await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve()));
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
for (const cause of ['missing-pin', 'bad-digest', 'conflicting-stdin', 'cancelled']) {
|
|
92
|
+
test('invalid portal-input ' + cause + ' stops before any request', async () => {
|
|
93
|
+
const f = fixture();
|
|
94
|
+
if (cause === 'missing-pin')
|
|
95
|
+
delete f.input.portalContextSha256;
|
|
96
|
+
if (cause === 'bad-digest')
|
|
97
|
+
f.input.portalPromptSha256 = 'not-a-digest';
|
|
98
|
+
if (cause === 'conflicting-stdin')
|
|
99
|
+
f.input.initialUserPrompt = prompt;
|
|
100
|
+
if (cause === 'cancelled')
|
|
101
|
+
f.input.signal = AbortSignal.abort();
|
|
102
|
+
await assert.rejects(requestCodexSetupHostPreparation(f.input));
|
|
103
|
+
assert.equal(f.calls, 0);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
for (const cause of ['prompt-change', 'embedded-digest', 'context-change', 'secret', 'oversized', 'foreign-org', 'foreign-reference', 'expired', 'wrong-source', 'v1-downgrade', 'extra-field']) {
|
|
107
|
+
test('portal-input ' + cause + ' is rejected without reflecting response data', async () => {
|
|
108
|
+
const f = fixture();
|
|
109
|
+
if (cause === 'prompt-change') {
|
|
110
|
+
f.response.publicPrompt += 'Unexpected instruction\n';
|
|
111
|
+
f.response.promptSha256 = createHash('sha256').update(f.response.publicPrompt).digest('hex');
|
|
112
|
+
}
|
|
113
|
+
if (cause === 'embedded-digest') {
|
|
114
|
+
f.response.publicPrompt = f.response.publicPrompt.replace('--portal-prompt-sha256 ' + portalDigest, '--portal-prompt-sha256 ' + 'e'.repeat(64));
|
|
115
|
+
f.response.promptSha256 = createHash('sha256').update(f.response.publicPrompt).digest('hex');
|
|
116
|
+
}
|
|
117
|
+
if (cause === 'context-change') {
|
|
118
|
+
f.response.context.policyRevision = 'changed';
|
|
119
|
+
f.response.integrity.contextSha256 = 'e'.repeat(64);
|
|
120
|
+
}
|
|
121
|
+
if (cause === 'secret')
|
|
122
|
+
f.response.publicPrompt += 'dhab_SYNTHETIC_PRIVATE_CANARY';
|
|
123
|
+
if (cause === 'oversized')
|
|
124
|
+
f.response.publicPrompt += 'x'.repeat(32768);
|
|
125
|
+
if (cause === 'foreign-org')
|
|
126
|
+
f.response.context.organizationId = 'org_foreign';
|
|
127
|
+
if (cause === 'foreign-reference')
|
|
128
|
+
f.response.context.setupReference = context.recipientMembershipId;
|
|
129
|
+
if (cause === 'expired')
|
|
130
|
+
f.response.expiresAt = new Date(now).toISOString();
|
|
131
|
+
if (cause === 'wrong-source')
|
|
132
|
+
f.response.promptSource = 'original_user_message';
|
|
133
|
+
if (cause === 'v1-downgrade')
|
|
134
|
+
f.response.schema = 'dharma.setup-host-preparation/v1';
|
|
135
|
+
if (cause === 'extra-field')
|
|
136
|
+
f.response.credential = 'PRIVATE_CANARY';
|
|
137
|
+
await assert.rejects(requestCodexSetupHostPreparation(f.input), error => error instanceof Error && error.message === 'codex_setup_portal_preparation_unavailable');
|
|
138
|
+
assert.equal(f.calls, 1);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=codexSetupPortalPrompt.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPrompt.test.js","sourceRoot":"","sources":["../src/codexSetupPortalPrompt.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPromptDigest.d.ts","sourceRoot":"","sources":["../src/codexSetupPortalPromptDigest.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAWnE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
/** The single public checksum argument is zeroed to avoid a self-referential digest. */
|
|
3
|
+
export function codexSetupPortalPromptDigest(value) {
|
|
4
|
+
const invalid = () => { throw new Error('codex_setup_public_prompt_invalid'); };
|
|
5
|
+
if (typeof value !== 'string' || !value || Buffer.byteLength(value) > 32768
|
|
6
|
+
|| Buffer.from(value, 'utf8').toString('utf8') !== value
|
|
7
|
+
|| /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/.test(value))
|
|
8
|
+
return invalid();
|
|
9
|
+
const text = value.replace(/\r\n/g, '\n');
|
|
10
|
+
if ([...text.matchAll(/--portal-prompt-sha256\b/g)].length !== 1)
|
|
11
|
+
return invalid();
|
|
12
|
+
const matches = [...text.matchAll(/--portal-prompt-sha256 ([a-f0-9]{64})(?=[ \t\n]|$)/g)];
|
|
13
|
+
if (matches.length !== 1)
|
|
14
|
+
return invalid();
|
|
15
|
+
const match = matches[0], at = match.index + match[0].length - 64;
|
|
16
|
+
return createHash('sha256').update(text.slice(0, at) + '0'.repeat(64) + text.slice(at + 64), 'utf8').digest('hex');
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=codexSetupPortalPromptDigest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPromptDigest.js","sourceRoot":"","sources":["../src/codexSetupPortalPromptDigest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAEvC,wFAAwF;AACxF,MAAM,UAAU,4BAA4B,CAAC,KAAc;IACzD,MAAM,OAAO,GAAC,GAAQ,EAAE,GAAC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC,CAAA,CAAC,CAAC;IAChF,IAAG,OAAO,KAAK,KAAG,QAAQ,IAAE,CAAC,KAAK,IAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,GAAC,KAAK;WAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,EAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAG,KAAK;WAClD,gDAAgD,CAAC,IAAI,CAAC,KAAK,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;IAClF,MAAM,IAAI,GAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAC,IAAI,CAAC,CAAC;IACvC,IAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,CAAC,MAAM,KAAG,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;IAC/E,MAAM,OAAO,GAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,qDAAqD,CAAC,CAAC,CAAC;IACxF,IAAG,OAAO,CAAC,MAAM,KAAG,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;IACvC,MAAM,KAAK,GAAC,OAAO,CAAC,CAAC,CAAE,EAAC,EAAE,GAAC,KAAK,CAAC,KAAM,GAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAC,EAAE,CAAC;IAC3D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAC,EAAE,CAAC,GAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAC,EAAE,CAAC,EAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC7G,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPromptDigest.test.d.ts","sourceRoot":"","sources":["../src/codexSetupPortalPromptDigest.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import test from 'node:test';
|
|
4
|
+
import { codexSetupPortalPromptDigest } from './codexSetupPortalPromptDigest.js';
|
|
5
|
+
const empty = '0'.repeat(64);
|
|
6
|
+
const template = '# Public setup specification\nRun the official entry --portal-prompt-sha256 ' + empty + '\n';
|
|
7
|
+
const expected = createHash('sha256').update(template).digest('hex');
|
|
8
|
+
test('portal prompt checksum masks only its single checksum argument, not other instructions', () => {
|
|
9
|
+
assert.equal(codexSetupPortalPromptDigest(template), expected);
|
|
10
|
+
const filled = template.replace(empty, expected);
|
|
11
|
+
assert.equal(codexSetupPortalPromptDigest(filled), expected);
|
|
12
|
+
assert.equal(codexSetupPortalPromptDigest(filled.replaceAll('\n', '\r\n')), expected);
|
|
13
|
+
assert.notEqual(codexSetupPortalPromptDigest(filled.replace('official', 'foreign')), expected);
|
|
14
|
+
assert.notEqual(codexSetupPortalPromptDigest(filled + 'Extra instruction\n'), expected);
|
|
15
|
+
});
|
|
16
|
+
for (const value of [null, '', template.replace('--portal-prompt-sha256 ', '--unknown '),
|
|
17
|
+
template + template, template.replace(empty, 'g'.repeat(64)), template.replace(empty, empty + 'a'),
|
|
18
|
+
template.replace(empty, empty + '\0'), template + 'x'.repeat(32768)]) {
|
|
19
|
+
test('malformed or ambiguous checksum input is not accepted: ' + String(value).slice(0, 45), () => {
|
|
20
|
+
assert.throws(() => codexSetupPortalPromptDigest(value), /^Error: codex_setup_public_prompt_invalid$/);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=codexSetupPortalPromptDigest.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPortalPromptDigest.test.js","sourceRoot":"","sources":["../src/codexSetupPortalPromptDigest.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,4BAA4B,EAAC,MAAM,mCAAmC,CAAC;AAE/E,MAAM,KAAK,GAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC3B,MAAM,QAAQ,GAAC,8EAA8E,GAAC,KAAK,GAAC,IAAI,CAAC;AACzG,MAAM,QAAQ,GAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACnE,IAAI,CAAC,wFAAwF,EAAC,GAAE,EAAE;IAChG,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,QAAQ,CAAC,EAAC,QAAQ,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,MAAM,CAAC,EAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,CAAC,4BAA4B,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,EAAC,QAAQ,CAAC,CAAC;IACpF,MAAM,CAAC,QAAQ,CAAC,4BAA4B,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAC,SAAS,CAAC,CAAC,EAAC,QAAQ,CAAC,CAAC;IAC7F,MAAM,CAAC,QAAQ,CAAC,4BAA4B,CAAC,MAAM,GAAC,qBAAqB,CAAC,EAAC,QAAQ,CAAC,CAAC;AACvF,CAAC,CAAC,CAAC;AACH,KAAI,MAAM,KAAK,IAAI,CAAC,IAAI,EAAC,EAAE,EAAC,QAAQ,CAAC,OAAO,CAAC,yBAAyB,EAAC,YAAY,CAAC;IAClF,QAAQ,GAAC,QAAQ,EAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAC,KAAK,GAAC,GAAG,CAAC;IAC1F,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAC,KAAK,GAAC,IAAI,CAAC,EAAC,QAAQ,GAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAC,CAAC;IAChE,IAAI,CAAC,yDAAyD,GAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAC,EAAE,CAAC,EAAC,GAAE,EAAE;QAC3F,MAAM,CAAC,MAAM,CAAC,GAAE,EAAE,CAAA,4BAA4B,CAAC,KAAK,CAAC,EAAC,4CAA4C,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
/** Agent-supplied public text only; never a terminal password/grant prompt. */
|
|
3
|
+
export declare function readCodexSetupPublicStdin(stream: Readable & {
|
|
4
|
+
isTTY?: boolean;
|
|
5
|
+
}, signal: AbortSignal): Promise<string>;
|
|
6
|
+
//# sourceMappingURL=codexSetupPublicStdin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPublicStdin.d.ts","sourceRoot":"","sources":["../src/codexSetupPublicStdin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAG1C,+EAA+E;AAC/E,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,QAAQ,GAAG;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB1H"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { capturePublicCodexSetupPrompt } from './codexSetupUserPrompt.js';
|
|
2
|
+
/** Agent-supplied public text only; never a terminal password/grant prompt. */
|
|
3
|
+
export async function readCodexSetupPublicStdin(stream, signal) {
|
|
4
|
+
const fail = () => new Error('codex_setup_public_input_unavailable');
|
|
5
|
+
if (stream.isTTY || signal.aborted)
|
|
6
|
+
throw fail();
|
|
7
|
+
const deadline = AbortSignal.any([signal, AbortSignal.timeout(15000)]);
|
|
8
|
+
const cancel = () => stream.destroy(fail());
|
|
9
|
+
deadline.addEventListener('abort', cancel, { once: true });
|
|
10
|
+
const chunks = [];
|
|
11
|
+
let size = 0;
|
|
12
|
+
try {
|
|
13
|
+
for await (const chunk of stream) {
|
|
14
|
+
if (deadline.aborted)
|
|
15
|
+
throw fail();
|
|
16
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
17
|
+
size += bytes.length;
|
|
18
|
+
if (size > 32768)
|
|
19
|
+
throw fail();
|
|
20
|
+
chunks.push(bytes);
|
|
21
|
+
}
|
|
22
|
+
if (deadline.aborted)
|
|
23
|
+
throw fail();
|
|
24
|
+
const bytes = Buffer.concat(chunks), text = bytes.toString('utf8');
|
|
25
|
+
if (!Buffer.from(text, 'utf8').equals(bytes))
|
|
26
|
+
throw fail();
|
|
27
|
+
return capturePublicCodexSetupPrompt(text);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw fail();
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
deadline.removeEventListener('abort', cancel);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=codexSetupPublicStdin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPublicStdin.js","sourceRoot":"","sources":["../src/codexSetupPublicStdin.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,6BAA6B,EAAC,MAAM,2BAA2B,CAAC;AAExE,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,MAAoC,EAAE,MAAmB;IACvG,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACrE,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,OAAO;QAAE,MAAM,IAAI,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IACzD,MAAM,MAAM,GAAa,EAAE,CAAC;IAAC,IAAI,IAAI,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,OAAO;gBAAE,MAAM,IAAI,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClE,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;YACrB,IAAI,IAAI,GAAG,KAAK;gBAAE,MAAM,IAAI,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,QAAQ,CAAC,OAAO;YAAE,MAAM,IAAI,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,EAAE,CAAC;QAC3D,OAAO,6BAA6B,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QAAA,MAAM,IAAI,EAAE,CAAC;IAAA,CAAC;YACf,CAAC;QAAA,QAAQ,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAAA,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPublicStdin.test.d.ts","sourceRoot":"","sources":["../src/codexSetupPublicStdin.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { PassThrough, Readable } from 'node:stream';
|
|
3
|
+
import test from 'node:test';
|
|
4
|
+
import { readCodexSetupPublicStdin } from './codexSetupPublicStdin.js';
|
|
5
|
+
const prompt = '# Public setup\r\nOriginal text is preserved.\n';
|
|
6
|
+
test('public stdin preserves valid original bytes across chunks without echo or file transport', async () => {
|
|
7
|
+
const stream = Readable.from([Buffer.from(prompt.slice(0, 8)), Buffer.from(prompt.slice(8))]);
|
|
8
|
+
assert.equal(await readCodexSetupPublicStdin(stream, new AbortController().signal), prompt);
|
|
9
|
+
});
|
|
10
|
+
for (const reason of ['tty', 'cancelled']) {
|
|
11
|
+
test(`public stdin refuses ${reason} before reading`, async () => {
|
|
12
|
+
let reads = 0;
|
|
13
|
+
const stream = new Readable({ read() { reads++; this.push(null); } });
|
|
14
|
+
const control = new AbortController();
|
|
15
|
+
if (reason === 'tty')
|
|
16
|
+
stream.isTTY = true;
|
|
17
|
+
else
|
|
18
|
+
control.abort();
|
|
19
|
+
await assert.rejects(readCodexSetupPublicStdin(stream, control.signal), /^Error: codex_setup_public_input_unavailable$/);
|
|
20
|
+
assert.equal(reads, 0);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
for (const [reason, bytes] of [
|
|
24
|
+
['oversized', Buffer.alloc(32769, 97)], ['invalid-utf8', Buffer.from([0xc3, 0x28])],
|
|
25
|
+
['empty', Buffer.alloc(0)], ['credential', Buffer.from(['dhab', 'synthetic', 'never-real'].join('_'))],
|
|
26
|
+
]) {
|
|
27
|
+
test(`public stdin rejects ${reason} with a constant non-disclosing result`, async () => {
|
|
28
|
+
await assert.rejects(readCodexSetupPublicStdin(Readable.from([bytes]), new AbortController().signal), /^Error: codex_setup_public_input_unavailable$/);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
test('cancellation destroys only the owned waiting public input stream', async () => {
|
|
32
|
+
const stream = new PassThrough(), other = new PassThrough(), control = new AbortController();
|
|
33
|
+
const reading = readCodexSetupPublicStdin(stream, control.signal);
|
|
34
|
+
control.abort();
|
|
35
|
+
await assert.rejects(reading, /^Error: codex_setup_public_input_unavailable$/);
|
|
36
|
+
assert.equal(stream.destroyed, true);
|
|
37
|
+
assert.equal(other.destroyed, false);
|
|
38
|
+
other.destroy();
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=codexSetupPublicStdin.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexSetupPublicStdin.test.js","sourceRoot":"","sources":["../src/codexSetupPublicStdin.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,8 @@ export type CodexSetupPromptBinding = Readonly<{
|
|
|
5
5
|
}>;
|
|
6
6
|
/** Public fields captured from the independently verified recipient/selection. */
|
|
7
7
|
export declare function captureCodexSetupPromptBinding(value: unknown): CodexSetupPromptBinding;
|
|
8
|
+
/** Reject credential-bearing public prose before network or persistence. */
|
|
9
|
+
export declare function capturePublicCodexSetupPrompt(value: unknown): string;
|
|
8
10
|
/** Presentation consistency only. The original host intent and lease, never
|
|
9
11
|
* model-visible prose, remain the authority for every protected setup effect. */
|
|
10
12
|
export declare function captureCodexSetupUserPrompt(value: unknown, intent: Readonly<CodexSetupIntent>, suppliedBinding?: unknown): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codexSetupUserPrompt.d.ts","sourceRoot":"","sources":["../src/codexSetupUserPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAI/D,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAEtG,kFAAkF;AAClF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAmBtF;AAED;iFACiF;AACjF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"codexSetupUserPrompt.d.ts","sourceRoot":"","sources":["../src/codexSetupUserPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;AAI/D,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAC,CAAC,CAAC;AAEtG,kFAAkF;AAClF,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAmBtF;AAED,4EAA4E;AAC5E,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAepE;AAED;iFACiF;AACjF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAiB7I"}
|
|
@@ -29,11 +29,8 @@ export function captureCodexSetupPromptBinding(value) {
|
|
|
29
29
|
}
|
|
30
30
|
return Object.freeze({ recipientEmail, repositoryRemoteUrl });
|
|
31
31
|
}
|
|
32
|
-
/**
|
|
33
|
-
|
|
34
|
-
export function captureCodexSetupUserPrompt(value, intent, suppliedBinding) {
|
|
35
|
-
if (value === undefined)
|
|
36
|
-
return undefined;
|
|
32
|
+
/** Reject credential-bearing public prose before network or persistence. */
|
|
33
|
+
export function capturePublicCodexSetupPrompt(value) {
|
|
37
34
|
const invalid = () => { throw new Error('codex_setup_public_prompt_invalid'); };
|
|
38
35
|
if (typeof value !== 'string' || !value || Buffer.byteLength(value, 'utf8') > 32_768
|
|
39
36
|
|| Buffer.from(value, 'utf8').toString('utf8') !== value
|
|
@@ -49,7 +46,16 @@ export function captureCodexSetupUserPrompt(value, intent, suppliedBinding) {
|
|
|
49
46
|
|| /\b(?:gh[pousr]_|github_pat_|sk_live_|sk_test_)[A-Za-z0-9_]{12,}|\bBearer\s+[A-Za-z0-9_.+-]{8,}/i.test(value)
|
|
50
47
|
|| /\b[A-Za-z0-9_]*(?:password|passwd|secret|api_key|access_token|refresh_token|credentials?|token)(?:_[A-Za-z0-9_]+)?["']?\s*[:=]\s*["']?[^\s"',;]+/i.test(value))
|
|
51
48
|
return invalid();
|
|
52
|
-
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
/** Presentation consistency only. The original host intent and lease, never
|
|
52
|
+
* model-visible prose, remain the authority for every protected setup effect. */
|
|
53
|
+
export function captureCodexSetupUserPrompt(value, intent, suppliedBinding) {
|
|
54
|
+
if (value === undefined)
|
|
55
|
+
return undefined;
|
|
56
|
+
const prompt = capturePublicCodexSetupPrompt(value);
|
|
57
|
+
const invalid = () => { throw new Error('codex_setup_public_prompt_invalid'); };
|
|
58
|
+
const binding = captureCodexSetupPromptBinding(suppliedBinding), lines = prompt.split(/\r?\n/);
|
|
53
59
|
const only = (prefix) => {
|
|
54
60
|
const selected = lines.filter(line => line.startsWith(prefix));
|
|
55
61
|
if (selected.length !== 1)
|
|
@@ -62,6 +68,6 @@ export function captureCodexSetupUserPrompt(value, intent, suppliedBinding) {
|
|
|
62
68
|
|| only('Public setup reference: ') !== `Public setup reference: ${intent.setupReference}. Fixed expiry: ${intent.expiresAt}.`) {
|
|
63
69
|
return invalid();
|
|
64
70
|
}
|
|
65
|
-
return
|
|
71
|
+
return prompt;
|
|
66
72
|
}
|
|
67
73
|
//# sourceMappingURL=codexSetupUserPrompt.js.map
|