@dharma-ai-labs/agent-fabric 0.2.131 → 0.2.133

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 (34) hide show
  1. package/AGENT_FABRIC_ONBOARDING.md +11 -9
  2. package/README.md +21 -0
  3. package/dist/bootstrapResume.test.js +1 -1
  4. package/dist/bootstrapResume.test.js.map +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +32 -4
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.test.js +6 -3
  9. package/dist/index.test.js.map +1 -1
  10. package/dist/onboardingContract.test.js +13 -2
  11. package/dist/onboardingContract.test.js.map +1 -1
  12. package/dist/privateGrantInput.d.ts +27 -0
  13. package/dist/privateGrantInput.d.ts.map +1 -0
  14. package/dist/privateGrantInput.js +159 -0
  15. package/dist/privateGrantInput.js.map +1 -0
  16. package/dist/privateGrantInput.test.d.ts +2 -0
  17. package/dist/privateGrantInput.test.d.ts.map +1 -0
  18. package/dist/privateGrantInput.test.js +136 -0
  19. package/dist/privateGrantInput.test.js.map +1 -0
  20. package/dist/repositoryJoinConnection.d.ts +18 -0
  21. package/dist/repositoryJoinConnection.d.ts.map +1 -0
  22. package/dist/repositoryJoinConnection.js +48 -0
  23. package/dist/repositoryJoinConnection.js.map +1 -0
  24. package/dist/repositoryJoinConnection.test.d.ts +2 -0
  25. package/dist/repositoryJoinConnection.test.d.ts.map +1 -0
  26. package/dist/repositoryJoinConnection.test.js +108 -0
  27. package/dist/repositoryJoinConnection.test.js.map +1 -0
  28. package/dist/repositoryOnboardingCaller.test.js +74 -1
  29. package/dist/repositoryOnboardingCaller.test.js.map +1 -1
  30. package/dist/usage.d.ts +1 -1
  31. package/dist/usage.d.ts.map +1 -1
  32. package/dist/usage.js +2 -1
  33. package/dist/usage.js.map +1 -1
  34. package/package.json +1 -1
@@ -10,8 +10,19 @@ test('the installed onboarding contract forbids product-code workarounds', async
10
10
  assert.match(contract, /do not bypass enrollment/i);
11
11
  assert.match(contract, /exact failed stage, non-sensitive error, and correlation ID/i);
12
12
  assert.match(contract, /supported retry, reconciliation, rollback, or browser-authorized re-enrollment/i);
13
- assert.match(contract, /one retry of the unchanged command is permitted before grant expiry/i);
14
- assert.match(contract, /Never retry a grant after redemption/i);
13
+ assert.match(contract, /retry the unchanged command once before expiry when the receipt explicitly proves non-redemption/i);
14
+ assert.match(contract, /After redemption, approval or another error, use only the supported cause-specific grant-free recovery; never replay the grant/i);
15
+ });
16
+ test('the installed contract separates agent instructions from recipient-only private terminal entry', async () => {
17
+ const contract = await readFile(contractUrl, 'utf8');
18
+ assert.match(contract, /short-lived grant is a separate recipient-only private field, not part of the agent prompt/i);
19
+ assert.match(contract, /exact generated grant-free `--grant-prompt` command directly in their own private, unrecorded interactive terminal/i);
20
+ assert.match(contract, /Never receive, print, save, commit, place in argv or environment, send through agent tools or transport, or record that grant/i);
21
+ assert.match(contract, /cannot detect an external recorder or prove the human owns a TTY/i);
22
+ assert.match(contract, /no supplementary manual setup command/i);
23
+ assert.match(contract, /Join existing[\s\S]*No GitHub permission or source checkout is needed/i);
24
+ assert.match(contract, /legacy Demo command contract does not establish `--grant-prompt` support/i);
25
+ assert.doesNotMatch(contract, /only routine human action|setup envelope contains[\s\S]*one-time grant/i);
15
26
  });
16
27
  test('the installed guide names the supported knowledge and peer workflow', async () => {
17
28
  const contract = await readFile(contractUrl, 'utf8');
@@ -1 +1 @@
1
- {"version":3,"file":"onboardingContract.test.js","sourceRoot":"","sources":["../src/onboardingContract.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE9E,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;IACpF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gDAAgD,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,0CAA0C,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACpD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,8DAA8D,CAAC,CAAC;IACvF,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iFAAiF,CAAC,CAAC;IAC1G,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,sEAAsE,CAAC,CAAC;IAC/F,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,uCAAuC,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;IACrF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,kHAAkH,CAAC,CAAC;IAC3I,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gFAAgF,CAAC,CAAC;IACzG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,oHAAoH,CAAC,CAAC;IAC7I,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,8EAA8E,CAAC,CAAC;IACvG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,qDAAqD,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iDAAiD,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,sDAAsD,CAAC,CAAC;IAC/E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,wDAAwD,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,4EAA4E,CAAC,CAAC;IACrG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"onboardingContract.test.js","sourceRoot":"","sources":["../src/onboardingContract.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE9E,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;IACpF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gDAAgD,CAAC,CAAC;IACzE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,0CAA0C,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IACpD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,8DAA8D,CAAC,CAAC;IACvF,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iFAAiF,CAAC,CAAC;IAC1G,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,mGAAmG,CAAC,CAAC;IAC5H,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iIAAiI,CAAC,CAAC;AAC5J,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gGAAgG,EAAE,KAAK,IAAI,EAAE;IAChH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,6FAA6F,CAAC,CAAC;IACtH,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,qHAAqH,CAAC,CAAC;IAC9I,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gIAAgI,CAAC,CAAC;IACzJ,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,mEAAmE,CAAC,CAAC;IAC5F,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,wCAAwC,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,wEAAwE,CAAC,CAAC;IACjG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,2EAA2E,CAAC,CAAC;IACpG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,yEAAyE,CAAC,CAAC;AAC3G,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;IACrF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAErD,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,kHAAkH,CAAC,CAAC;IAC3I,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,gFAAgF,CAAC,CAAC;IACzG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,oHAAoH,CAAC,CAAC;IAC7I,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,8EAA8E,CAAC,CAAC;IACvG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,qDAAqD,CAAC,CAAC;IAC9E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,iDAAiD,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,sDAAsD,CAAC,CAAC;IAC/E,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,wDAAwD,CAAC,CAAC;IACjF,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,mCAAmC,CAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,4EAA4E,CAAC,CAAC;IACrG,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,qBAAqB,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { EventEmitter } from 'node:events';
2
+ type TerminalInput = Pick<EventEmitter, 'on' | 'removeListener' | 'listenerCount'> & {
3
+ isTTY: boolean;
4
+ isRaw: boolean;
5
+ fd: number;
6
+ readableFlowing: boolean | null;
7
+ setRawMode(raw: boolean): unknown;
8
+ resume(): unknown;
9
+ pause(): unknown;
10
+ };
11
+ type TerminalOutput = {
12
+ isTTY: boolean;
13
+ fd: number;
14
+ write(value: string): unknown;
15
+ };
16
+ type Signals = Pick<EventEmitter, 'on' | 'removeListener'>;
17
+ interface PrivateGrantTerminal {
18
+ input: TerminalInput;
19
+ output: TerminalOutput;
20
+ signals: Signals;
21
+ isTerminal: (fd: number) => boolean;
22
+ }
23
+ export declare function bootstrapGrantMode(flags: Map<string, string | boolean>): 'resume' | 'argument' | 'prompt';
24
+ /** Read only from the user's own terminal. No pipe, environment, file or echo fallback. */
25
+ export declare function readPrivateBootstrapGrant(terminal?: PrivateGrantTerminal): Promise<string>;
26
+ export {};
27
+ //# sourceMappingURL=privateGrantInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privateGrantInput.d.ts","sourceRoot":"","sources":["../src/privateGrantInput.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,KAAK,aAAa,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,gBAAgB,GAAG,eAAe,CAAC,GAAG;IACnF,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5E,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC;IAAC,MAAM,IAAI,OAAO,CAAC;IAAC,KAAK,IAAI,OAAO,CAAC;CACxE,CAAC;AACF,KAAK,cAAc,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AACpF,KAAK,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,GAAG,gBAAgB,CAAC,CAAC;AAC3D,UAAU,oBAAoB;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;CACrC;AAKD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAYzG;AAED,2FAA2F;AAC3F,wBAAsB,yBAAyB,CAAC,QAAQ,GAAE,oBAGzD,GAAG,OAAO,CAAC,MAAM,CAAC,CAmFlB"}
@@ -0,0 +1,159 @@
1
+ import { isatty } from 'node:tty';
2
+ const MAX_GRANT_BYTES = 16_384;
3
+ const CANCEL_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGTSTP'];
4
+ export function bootstrapGrantMode(flags) {
5
+ const grant = flags.get('grant');
6
+ const prompt = flags.get('grant-prompt');
7
+ if ((flags.has('resume') && (flags.has('grant') || flags.has('grant-prompt')))
8
+ || (flags.has('grant') && flags.has('grant-prompt'))
9
+ || (flags.has('grant-prompt') && prompt !== true)) {
10
+ throw new Error('bootstrap_grant_options_invalid: --grant-prompt takes no value and cannot be combined with --grant or --resume.');
11
+ }
12
+ if (flags.has('resume'))
13
+ return 'resume';
14
+ if (prompt === true)
15
+ return 'prompt';
16
+ if (typeof grant === 'string' && grant.length > 0)
17
+ return 'argument';
18
+ throw new Error('bootstrap_grant_options_invalid: use --grant-prompt for private terminal entry, or an existing supported --grant invocation.');
19
+ }
20
+ /** Read only from the user's own terminal. No pipe, environment, file or echo fallback. */
21
+ export async function readPrivateBootstrapGrant(terminal = {
22
+ input: process.stdin, output: process.stderr,
23
+ signals: process, isTerminal: isatty,
24
+ }) {
25
+ const { input, output, signals, isTerminal } = terminal;
26
+ if (!input.isTTY || !output.isTTY || !isTerminal(input.fd) || !isTerminal(output.fd)
27
+ || input.isRaw || input.listenerCount('data') !== 0) {
28
+ throw new Error('private_grant_terminal_required: run this command directly in your own interactive terminal; do not pipe, redirect or send the grant through an agent.');
29
+ }
30
+ const wasFlowing = input.readableFlowing;
31
+ const bytes = Buffer.alloc(MAX_GRANT_BYTES);
32
+ let length = 0;
33
+ let finished = false;
34
+ let escape = '';
35
+ let pasting = false;
36
+ let escapeTimer;
37
+ let inputTimer;
38
+ return new Promise((resolve, reject) => {
39
+ const restore = () => {
40
+ clearTimeout(escapeTimer);
41
+ clearTimeout(inputTimer);
42
+ input.removeListener('data', onData);
43
+ input.removeListener('end', onFailure);
44
+ input.removeListener('close', onFailure);
45
+ input.removeListener('error', onFailure);
46
+ for (const signal of CANCEL_SIGNALS)
47
+ signals.removeListener(signal, onCancel);
48
+ signals.removeListener('exit', onExit);
49
+ bytes.fill(0);
50
+ length = 0;
51
+ try {
52
+ if (input.isRaw)
53
+ input.setRawMode(false);
54
+ if (wasFlowing === true)
55
+ input.resume();
56
+ else
57
+ input.pause();
58
+ return true;
59
+ }
60
+ catch {
61
+ return false;
62
+ }
63
+ };
64
+ const finish = (code, value) => {
65
+ if (finished)
66
+ return;
67
+ finished = true;
68
+ const restored = restore();
69
+ try {
70
+ output.write('\n');
71
+ }
72
+ catch { /* Never print input or an underlying error. */ }
73
+ if (code || !restored)
74
+ reject(new Error(code || 'private_grant_input_failed'));
75
+ else
76
+ resolve(value);
77
+ };
78
+ const onCancel = () => finish('private_grant_cancelled');
79
+ const onFailure = () => finish('private_grant_input_failed');
80
+ const onExit = () => { finished = true; restore(); };
81
+ const onData = (data) => {
82
+ const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
83
+ if (chunk.length > MAX_GRANT_BYTES + 14) {
84
+ finish('private_grant_too_large');
85
+ return;
86
+ }
87
+ for (let index = 0; index < chunk.length; index += 1) {
88
+ const byte = chunk[index];
89
+ if (escape || byte === 27) {
90
+ escape += String.fromCharCode(byte);
91
+ const start = '\x1b[200~';
92
+ const end = '\x1b[201~';
93
+ if (escape === start && !pasting && length === 0) {
94
+ pasting = true;
95
+ escape = '';
96
+ clearTimeout(escapeTimer);
97
+ }
98
+ else if (escape === end && pasting) {
99
+ pasting = false;
100
+ escape = '';
101
+ clearTimeout(escapeTimer);
102
+ }
103
+ else if (!start.startsWith(escape) && !end.startsWith(escape)) {
104
+ onCancel();
105
+ return;
106
+ }
107
+ else {
108
+ clearTimeout(escapeTimer);
109
+ escapeTimer = setTimeout(onCancel, 1_000);
110
+ }
111
+ continue;
112
+ }
113
+ if ([3, 4, 26].includes(byte)) {
114
+ onCancel();
115
+ return;
116
+ }
117
+ if (byte === 10 || byte === 13) {
118
+ if (pasting || length === 0 || chunk.subarray(index + 1).some((next) => next !== 10 && next !== 13)) {
119
+ finish('private_grant_invalid');
120
+ return;
121
+ }
122
+ finish(undefined, bytes.subarray(0, length).toString('ascii'));
123
+ return;
124
+ }
125
+ if (byte === 8 || byte === 127) {
126
+ if (length > 0)
127
+ bytes[--length] = 0;
128
+ continue;
129
+ }
130
+ if (byte < 33 || byte > 126) {
131
+ finish('private_grant_invalid');
132
+ return;
133
+ }
134
+ if (length === MAX_GRANT_BYTES) {
135
+ finish('private_grant_too_large');
136
+ return;
137
+ }
138
+ bytes[length++] = byte;
139
+ }
140
+ };
141
+ input.on('data', onData);
142
+ input.on('end', onFailure);
143
+ input.on('close', onFailure);
144
+ input.on('error', onFailure);
145
+ for (const signal of CANCEL_SIGNALS)
146
+ signals.on(signal, onCancel);
147
+ signals.on('exit', onExit);
148
+ try {
149
+ input.setRawMode(true);
150
+ output.write('Paste your short-lived setup grant here, then press Enter (input hidden; Ctrl+C cancels): ');
151
+ inputTimer = setTimeout(() => finish('private_grant_cancelled'), 300_000);
152
+ input.resume();
153
+ }
154
+ catch {
155
+ onFailure();
156
+ }
157
+ });
158
+ }
159
+ //# sourceMappingURL=privateGrantInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privateGrantInput.js","sourceRoot":"","sources":["../src/privateGrantInput.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=privateGrantInput.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privateGrantInput.test.d.ts","sourceRoot":"","sources":["../src/privateGrantInput.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,136 @@
1
+ import assert from 'node:assert/strict';
2
+ import { EventEmitter } from 'node:events';
3
+ import test from 'node:test';
4
+ import { bootstrapGrantMode, readPrivateBootstrapGrant } from './privateGrantInput.js';
5
+ class Terminal extends EventEmitter {
6
+ isTTY = true;
7
+ isRaw = false;
8
+ readableFlowing = false;
9
+ fd = 0;
10
+ modes = [];
11
+ setRawMode(raw) { this.isRaw = raw; this.modes.push(raw); return this; }
12
+ resume() { this.readableFlowing = true; return this; }
13
+ pause() { this.readableFlowing = false; return this; }
14
+ }
15
+ function fixture() {
16
+ const input = new Terminal();
17
+ const signals = new EventEmitter();
18
+ const writes = [];
19
+ const output = { isTTY: true, fd: 2, write(value) { writes.push(value); return true; } };
20
+ return { input, output, signals, writes, isTerminal: () => true };
21
+ }
22
+ const fakeGrant = 'synthetic-not-a-real-grant';
23
+ function restored(io) {
24
+ assert.equal(io.input.isRaw, false);
25
+ assert.equal(io.input.readableFlowing, false);
26
+ assert.equal(io.input.listenerCount('data'), 0);
27
+ for (const signal of ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGTSTP', 'exit'])
28
+ assert.equal(io.signals.listenerCount(signal), 0);
29
+ assert.equal(io.writes.join('').includes(fakeGrant), false);
30
+ }
31
+ test('private grant succeeds with raw input, no echo and terminal restoration', async () => {
32
+ const io = fixture();
33
+ const pending = readPrivateBootstrapGrant(io);
34
+ assert.equal(io.input.isRaw, true);
35
+ io.input.emit('data', Buffer.from(fakeGrant + '\r'));
36
+ assert.equal(await pending, fakeGrant);
37
+ assert.deepEqual(io.input.modes, [true, false]);
38
+ restored(io);
39
+ });
40
+ test('prompt rejects pipe/redirected output and already-owned terminal before changing it', async () => {
41
+ for (const change of [(io) => { io.input.isTTY = false; },
42
+ (io) => { io.output.isTTY = false; },
43
+ (io) => { io.input.isRaw = true; },
44
+ (io) => { io.input.on('data', () => { }); }]) {
45
+ const io = fixture();
46
+ change(io);
47
+ await assert.rejects(readPrivateBootstrapGrant(io), /private_grant_terminal_required/);
48
+ assert.deepEqual(io.input.modes, []);
49
+ }
50
+ const io = fixture();
51
+ io.isTerminal = () => false;
52
+ await assert.rejects(readPrivateBootstrapGrant(io), /private_grant_terminal_required/);
53
+ });
54
+ test('cancel, EOF, signals, stream failure and oversize restore without exposing input', async () => {
55
+ for (const event of ['ctrl-c', 'ctrl-d', 'escape', 'end', 'close', 'error', 'SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT', 'SIGTSTP', 'oversize']) {
56
+ const io = fixture();
57
+ const pending = readPrivateBootstrapGrant(io);
58
+ io.input.emit('data', Buffer.from(fakeGrant));
59
+ if (event === 'ctrl-c')
60
+ io.input.emit('data', Buffer.from([3]));
61
+ else if (event === 'ctrl-d')
62
+ io.input.emit('data', Buffer.from([4]));
63
+ else if (event === 'escape')
64
+ io.input.emit('data', Buffer.from([27]));
65
+ else if (event === 'oversize')
66
+ io.input.emit('data', Buffer.alloc(16_385, 65));
67
+ else if (['end', 'close', 'error'].includes(event))
68
+ io.input.emit(event, new Error(fakeGrant));
69
+ else
70
+ io.signals.emit(event);
71
+ await assert.rejects(pending, /private_grant_(cancelled|input_failed|too_large)/);
72
+ restored(io);
73
+ }
74
+ });
75
+ test('private entry rejects empty, multiline, whitespace, non-ASCII and control content', async () => {
76
+ for (const text of ['\r', fakeGrant + '\nsecond-command', 'bad token\r', 'é\r', '\x00\r']) {
77
+ const io = fixture();
78
+ const pending = readPrivateBootstrapGrant(io);
79
+ io.input.emit('data', Buffer.from(text));
80
+ await assert.rejects(pending, /private_grant_invalid/);
81
+ restored(io);
82
+ }
83
+ });
84
+ test('private entry handles backspace and split paste without echo', async () => {
85
+ const io = fixture();
86
+ const pending = readPrivateBootstrapGrant(io);
87
+ io.input.emit('data', Buffer.from('synthetic-not-a-real-grantX\x7f'));
88
+ io.input.emit('data', Buffer.from('\r\n'));
89
+ assert.equal(await pending, fakeGrant);
90
+ restored(io);
91
+ });
92
+ test('bracketed paste boundaries may be split without accepting a pasted command or newline', async () => {
93
+ const io = fixture();
94
+ const pending = readPrivateBootstrapGrant(io);
95
+ for (const piece of ['\x1b', '[20', '0~', fakeGrant, '\x1b[2', '01~', '\r']) {
96
+ io.input.emit('data', Buffer.from(piece));
97
+ }
98
+ assert.equal(await pending, fakeGrant);
99
+ restored(io);
100
+ const bad = fixture();
101
+ const rejected = readPrivateBootstrapGrant(bad);
102
+ bad.input.emit('data', Buffer.from('\x1b[200~' + fakeGrant + '\ncommand\x1b[201~'));
103
+ await assert.rejects(rejected, /private_grant_invalid/);
104
+ restored(bad);
105
+ });
106
+ test('process exit restores terminal without emitting private input', () => {
107
+ const io = fixture();
108
+ void readPrivateBootstrapGrant(io);
109
+ io.input.emit('data', Buffer.from(fakeGrant));
110
+ io.signals.emit('exit');
111
+ restored(io);
112
+ });
113
+ test('raw-mode setup and prompt-write failures are sanitized and restored', async () => {
114
+ for (const where of ['raw', 'write']) {
115
+ const io = fixture();
116
+ if (where === 'raw')
117
+ io.input.setRawMode = () => { throw new Error(fakeGrant); };
118
+ else
119
+ io.output.write = () => { throw new Error(fakeGrant); };
120
+ await assert.rejects(readPrivateBootstrapGrant(io), /private_grant_input_failed/);
121
+ assert.equal(io.input.listenerCount('data'), 0);
122
+ assert.equal(io.input.isRaw, false);
123
+ }
124
+ });
125
+ test('supported grant modes preserve legacy and resume while rejecting conflict/value confusion', () => {
126
+ const flags = (...values) => new Map(values);
127
+ assert.equal(bootstrapGrantMode(flags(['grant-prompt', true])), 'prompt');
128
+ assert.equal(bootstrapGrantMode(flags(['grant', fakeGrant])), 'argument');
129
+ assert.equal(bootstrapGrantMode(flags(['resume', true])), 'resume');
130
+ for (const values of [[['grant', fakeGrant], ['grant-prompt', true]],
131
+ [['resume', true], ['grant-prompt', true]], [['resume', true], ['grant', fakeGrant]],
132
+ [['grant-prompt', fakeGrant]], [['grant-prompt', 'false']], [['grant', true]], []]) {
133
+ assert.throws(() => bootstrapGrantMode(flags(...values)), /bootstrap_grant_options_invalid/);
134
+ }
135
+ });
136
+ //# sourceMappingURL=privateGrantInput.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privateGrantInput.test.js","sourceRoot":"","sources":["../src/privateGrantInput.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export type RepositoryJoinConnection = {
2
+ workspace: string;
3
+ workspaceId: string;
4
+ organizationId: string;
5
+ bindingId: string;
6
+ sourceFingerprint: string;
7
+ repositoryAgentId: string;
8
+ repositoryAgentKey: string;
9
+ controlBranch: string;
10
+ hqUrl: string;
11
+ policyRevision: string;
12
+ onboardingMarkdown: string;
13
+ };
14
+ export declare function installRepositoryJoinConnection(input: RepositoryJoinConnection): Promise<{
15
+ connectionPath: string;
16
+ accessMode: "knowledge_only";
17
+ }>;
18
+ //# sourceMappingURL=repositoryJoinConnection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryJoinConnection.d.ts","sourceRoot":"","sources":["../src/repositoryJoinConnection.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAGF,wBAAsB,+BAA+B,CAAC,KAAK,EAAE,wBAAwB;;;GA4CpF"}
@@ -0,0 +1,48 @@
1
+ import { mkdir, readFile, realpath } from 'node:fs/promises';
2
+ import { resolve } from 'node:path';
3
+ import { assertRepositoryInstallerOwnership, checkedPath, writeRepositoryInstallerFile } from './repositoryInstallerFiles.js';
4
+ // Join state is local metadata, never a source inventory or a signed release.
5
+ export async function installRepositoryJoinConnection(input) {
6
+ const ownership = await assertRepositoryInstallerOwnership(input.workspace, input.workspaceId);
7
+ const workspace = await realpath(input.workspace);
8
+ await checkedPath(workspace, resolve(workspace, '.dharma/join-identity.json'), 'file');
9
+ const marker = JSON.parse(await readFile(resolve(workspace, '.dharma/join-identity.json'), 'utf8'));
10
+ if (!marker || Object.keys(marker).sort().join(',') !== 'bindingId,organizationId,sourceFingerprint'
11
+ || marker.organizationId !== input.organizationId || marker.bindingId !== input.bindingId
12
+ || marker.sourceFingerprint !== input.sourceFingerprint) {
13
+ throw new Error('repository_join_workspace_identity_conflict');
14
+ }
15
+ const existing = await readFile(resolve(workspace, '.dharma/agent-fabric.json'), 'utf8')
16
+ .then(value => JSON.parse(value))
17
+ .catch(error => { if (error?.code === 'ENOENT')
18
+ return null; throw error; });
19
+ if (existing && (existing.schema !== 'dharma.repository-connection/v2'
20
+ || existing.organizationId !== input.organizationId || existing.workspaceId !== input.workspaceId
21
+ || existing.repositoryAgentId !== input.repositoryAgentId || existing.repositoryBindingId !== input.bindingId
22
+ || existing.hqUrl !== input.hqUrl || existing.accessMode !== 'knowledge_only')) {
23
+ throw new Error('repository_join_connection_scope_conflict');
24
+ }
25
+ if (ownership !== 'signed') {
26
+ await mkdir(resolve(workspace, '.agents/skills/dharma-agent-fabric/references'), { recursive: true, mode: 0o700 });
27
+ await writeRepositoryInstallerFile(workspace, '.agents/skills/dharma-agent-fabric/.dharma-agent-fabric.json', `${JSON.stringify({ managedBy: 'dharma-agent-fabric', workspaceId: input.workspaceId })}\n`);
28
+ await writeRepositoryInstallerFile(workspace, '.agents/skills/dharma-agent-fabric/SKILL.md', `---\nname: dharma-agent-fabric\ndescription: Shared repository knowledge and bounded team coordination.\n---\n\n${input.onboardingMarkdown}`);
29
+ await writeRepositoryInstallerFile(workspace, '.agents/skills/dharma-agent-fabric/references/organization.md', `# Joined repository\n\nOrganization: ${input.organizationId}\nWorkspace: ${input.workspaceId}\nRepository binding: ${input.bindingId}\nAccess: knowledge-only\n`);
30
+ }
31
+ const connection = {
32
+ schema: 'dharma.repository-connection/v2', hqUrl: input.hqUrl,
33
+ organizationId: input.organizationId, workspaceId: input.workspaceId,
34
+ repositoryAgentId: input.repositoryAgentId, repositoryBindingId: input.bindingId,
35
+ repositoryAgentKey: input.repositoryAgentKey, controlBranch: input.controlBranch,
36
+ policyRevision: input.policyRevision, accessMode: 'knowledge_only',
37
+ openapiUrl: `${input.hqUrl}/api/v1/agent-fabric/openapi.json`,
38
+ instructionsUrl: `${input.hqUrl}/api/v1/orgs/${input.organizationId}/agent-fabric/instructions`,
39
+ };
40
+ await writeRepositoryInstallerFile(workspace, '.dharma/agent-fabric.json', `${JSON.stringify(connection, null, 2)}\n`);
41
+ await writeRepositoryInstallerFile(workspace, '.dharma/repository-agent.json', `${JSON.stringify({
42
+ schema: 'dharma.repository-agent/v1', organizationId: input.organizationId,
43
+ organizationAgentId: input.repositoryAgentId, agentKey: input.repositoryAgentKey,
44
+ controlBranch: input.controlBranch, workspaceId: input.workspaceId,
45
+ }, null, 2)}\n`);
46
+ return { connectionPath: '.dharma/agent-fabric.json', accessMode: 'knowledge_only' };
47
+ }
48
+ //# sourceMappingURL=repositoryJoinConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryJoinConnection.js","sourceRoot":"","sources":["../src/repositoryJoinConnection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=repositoryJoinConnection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryJoinConnection.test.d.ts","sourceRoot":"","sources":["../src/repositoryJoinConnection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,108 @@
1
+ import assert from 'node:assert/strict';
2
+ import { mkdir, mkdtemp, readFile, readdir, rm, symlink, unlink, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import test from 'node:test';
6
+ import { installRepositoryJoinConnection } from './repositoryJoinConnection.js';
7
+ import { installNativeAgentFabricBootstrap, verifyAgentFabricSkillInstallation } from './index.js';
8
+ async function fixture(t) {
9
+ const workspace = await mkdtemp(join(tmpdir(), 'dharma-join-connection-'));
10
+ t.after(() => rm(workspace, { recursive: true, force: true }));
11
+ const input = { workspace, workspaceId: 'workspace-join', organizationId: 'org_join',
12
+ bindingId: 'binding-join', sourceFingerprint: `sha256:${'a'.repeat(64)}`,
13
+ repositoryAgentId: 'agent-join', repositoryAgentKey: 'repo:join', controlBranch: 'agents/join',
14
+ hqUrl: 'https://www.dharma-ai.io', policyRevision: 'policy-one', onboardingMarkdown: '# Operating contract\n' };
15
+ await mkdir(join(workspace, '.dharma'));
16
+ await writeFile(join(workspace, '.dharma/join-identity.json'), JSON.stringify({
17
+ organizationId: input.organizationId, bindingId: input.bindingId, sourceFingerprint: input.sourceFingerprint,
18
+ }));
19
+ return input;
20
+ }
21
+ test('join connection is persistent and resumes without source inventory or catalog creation', async (t) => {
22
+ const input = await fixture(t);
23
+ const result = await installRepositoryJoinConnection(input);
24
+ const path = join(input.workspace, result.connectionPath);
25
+ const first = await readFile(path, 'utf8');
26
+ await installRepositoryJoinConnection(input);
27
+ assert.equal(await readFile(path, 'utf8'), first);
28
+ assert.equal(JSON.parse(first).accessMode, 'knowledge_only');
29
+ assert.equal(JSON.parse(first).repositoryBindingId, input.bindingId);
30
+ assert.doesNotMatch(first, /token|grant|secret/i);
31
+ assert.ok(!first.includes(input.workspace));
32
+ assert.deepEqual((await readdir(join(input.workspace, '.agents/skills/dharma-agent-fabric'))).sort(), ['.dharma-agent-fabric.json', 'SKILL.md', 'references']);
33
+ assert.deepEqual((await readdir(join(input.workspace, '.dharma'))).sort(), ['agent-fabric.json', 'join-identity.json', 'repository-agent.json']);
34
+ });
35
+ test('foreign join identity is rejected before any connection write', async (t) => {
36
+ const input = await fixture(t);
37
+ await assert.rejects(installRepositoryJoinConnection({ ...input, organizationId: 'org_foreign' }), /repository_join_workspace_identity_conflict/);
38
+ assert.deepEqual(await readdir(join(input.workspace, '.dharma')), ['join-identity.json']);
39
+ });
40
+ test('foreign connection remains untouched on resume', async (t) => {
41
+ const input = await fixture(t);
42
+ await installRepositoryJoinConnection(input);
43
+ const path = join(input.workspace, '.dharma/agent-fabric.json');
44
+ const prior = JSON.parse(await readFile(path, 'utf8'));
45
+ await writeFile(path, JSON.stringify({ ...prior, workspaceId: 'foreign-workspace' }));
46
+ const before = await readFile(path, 'utf8');
47
+ await assert.rejects(installRepositoryJoinConnection(input), /repository_join_connection_scope_conflict/);
48
+ assert.equal(await readFile(path, 'utf8'), before);
49
+ });
50
+ test('join repair preserves signed skill and ownership byte-for-byte', async (t) => {
51
+ const input = await fixture(t);
52
+ const root = join(input.workspace, '.agents/skills/dharma-agent-fabric');
53
+ await mkdir(root, { recursive: true });
54
+ const signed = { skillId: 'dharma-agent-fabric', workspaceId: input.workspaceId,
55
+ bundleId: '11111111-1111-4111-8111-111111111111' };
56
+ await writeFile(join(root, '.dharma-agent-fabric.json'), JSON.stringify(signed));
57
+ await writeFile(join(root, 'SKILL.md'), '# Signed skill content\n');
58
+ await installRepositoryJoinConnection(input);
59
+ assert.equal(await readFile(join(root, 'SKILL.md'), 'utf8'), '# Signed skill content\n');
60
+ assert.equal(await readFile(join(root, '.dharma-agent-fabric.json'), 'utf8'), JSON.stringify(signed));
61
+ });
62
+ test('join refuses unmanaged skill files', async (t) => {
63
+ const input = await fixture(t);
64
+ const root = join(input.workspace, '.agents/skills/dharma-agent-fabric');
65
+ await mkdir(root, { recursive: true });
66
+ await writeFile(join(root, 'SKILL.md'), '# Customer skill\n');
67
+ await assert.rejects(installRepositoryJoinConnection(input), /unmanaged repository skill/);
68
+ assert.equal(await readFile(join(root, 'SKILL.md'), 'utf8'), '# Customer skill\n');
69
+ });
70
+ test('join connection repairs bootstrap verification without claiming signed lifecycle readiness', async (t) => {
71
+ const input = await fixture(t);
72
+ const previous = process.env.DHARMA_HOME;
73
+ const home = await mkdtemp(join(tmpdir(), 'dharma-join-test-home-'));
74
+ process.env.DHARMA_HOME = home;
75
+ t.after(async () => {
76
+ if (previous === undefined)
77
+ delete process.env.DHARMA_HOME;
78
+ else
79
+ process.env.DHARMA_HOME = previous;
80
+ await rm(home, { recursive: true, force: true });
81
+ });
82
+ const native = { provider: 'codex', workspace: input.workspace, workspaceId: input.workspaceId,
83
+ organizationId: input.organizationId, hqUrl: input.hqUrl, home, env: { HOME: home, CODEX_HOME: join(home, '.codex') } };
84
+ await installNativeAgentFabricBootstrap(native);
85
+ const before = await verifyAgentFabricSkillInstallation(native);
86
+ assert.equal(before.ready, false);
87
+ assert.equal(before.repositoryInstalled, false);
88
+ await installRepositoryJoinConnection(input);
89
+ const after = await verifyAgentFabricSkillInstallation(native);
90
+ assert.equal(after.ready, true);
91
+ assert.equal(after.workspaceId, input.workspaceId);
92
+ assert.equal(after.repositoryInstalled, true);
93
+ assert.equal(after.verificationScope, 'generic_bootstrap');
94
+ assert.equal(after.signedLifecycleReady, false);
95
+ assert.equal(after.activeBundleId, null);
96
+ });
97
+ test('join identity symlink is rejected without changing its target', async (t) => {
98
+ const input = await fixture(t);
99
+ const marker = join(input.workspace, '.dharma/join-identity.json');
100
+ const target = join(input.workspace, 'foreign-marker.json');
101
+ const original = await readFile(marker, 'utf8');
102
+ await writeFile(target, original);
103
+ await unlink(marker);
104
+ await symlink(target, marker);
105
+ await assert.rejects(installRepositoryJoinConnection(input), /symlink is forbidden/);
106
+ assert.equal(await readFile(target, 'utf8'), original);
107
+ });
108
+ //# sourceMappingURL=repositoryJoinConnection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryJoinConnection.test.js","sourceRoot":"","sources":["../src/repositoryJoinConnection.test.ts"],"names":[],"mappings":"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"}