@gate-forge/witness 0.0.0-stage → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +114 -2
- package/dist/adapter/contract-suite.d.ts +167 -0
- package/dist/adapter/contract-suite.d.ts.map +1 -0
- package/dist/adapter/contract-suite.js +348 -0
- package/dist/adapter/contract-suite.js.map +1 -0
- package/dist/adapter/contract.d.ts +266 -0
- package/dist/adapter/contract.d.ts.map +1 -0
- package/dist/adapter/contract.js +2 -0
- package/dist/adapter/contract.js.map +1 -0
- package/dist/adapter/index.d.ts +8 -0
- package/dist/adapter/index.d.ts.map +1 -0
- package/dist/adapter/index.js +2 -0
- package/dist/adapter/index.js.map +1 -0
- package/dist/adapter-kit/config.d.ts +163 -0
- package/dist/adapter-kit/config.d.ts.map +1 -0
- package/dist/adapter-kit/config.js +21 -0
- package/dist/adapter-kit/config.js.map +1 -0
- package/dist/adapter-kit/define.d.ts +47 -0
- package/dist/adapter-kit/define.d.ts.map +1 -0
- package/dist/adapter-kit/define.js +336 -0
- package/dist/adapter-kit/define.js.map +1 -0
- package/dist/adapter-kit/index.d.ts +34 -0
- package/dist/adapter-kit/index.d.ts.map +1 -0
- package/dist/adapter-kit/index.js +32 -0
- package/dist/adapter-kit/index.js.map +1 -0
- package/dist/adapter-kit/projection.d.ts +69 -0
- package/dist/adapter-kit/projection.d.ts.map +1 -0
- package/dist/adapter-kit/projection.js +85 -0
- package/dist/adapter-kit/projection.js.map +1 -0
- package/dist/adapter-kit/session.d.ts +105 -0
- package/dist/adapter-kit/session.d.ts.map +1 -0
- package/dist/adapter-kit/session.js +230 -0
- package/dist/adapter-kit/session.js.map +1 -0
- package/dist/client/witness-client.d.ts +193 -0
- package/dist/client/witness-client.d.ts.map +1 -0
- package/dist/client/witness-client.js +321 -0
- package/dist/client/witness-client.js.map +1 -0
- package/dist/constants.d.ts +189 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +197 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +16 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +21 -0
- package/dist/json.js.map +1 -0
- package/dist/queue/bullmq.d.ts +28 -0
- package/dist/queue/bullmq.d.ts.map +1 -0
- package/dist/queue/bullmq.js +210 -0
- package/dist/queue/bullmq.js.map +1 -0
- package/dist/queue/observer.d.ts +130 -0
- package/dist/queue/observer.d.ts.map +1 -0
- package/dist/queue/observer.js +179 -0
- package/dist/queue/observer.js.map +1 -0
- package/dist/surface.d.ts +211 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +268 -0
- package/dist/surface.js.map +1 -0
- package/dist/witness/adapter-registry.d.ts +92 -0
- package/dist/witness/adapter-registry.d.ts.map +1 -0
- package/dist/witness/adapter-registry.js +370 -0
- package/dist/witness/adapter-registry.js.map +1 -0
- package/dist/witness/behavior-request.d.ts +80 -0
- package/dist/witness/behavior-request.d.ts.map +1 -0
- package/dist/witness/behavior-request.js +335 -0
- package/dist/witness/behavior-request.js.map +1 -0
- package/dist/witness/behavior.d.ts +52 -0
- package/dist/witness/behavior.d.ts.map +1 -0
- package/dist/witness/behavior.js +118 -0
- package/dist/witness/behavior.js.map +1 -0
- package/dist/witness/bin.d.ts +21 -0
- package/dist/witness/bin.d.ts.map +1 -0
- package/dist/witness/bin.js +254 -0
- package/dist/witness/bin.js.map +1 -0
- package/dist/witness/browser.d.ts +221 -0
- package/dist/witness/browser.d.ts.map +1 -0
- package/dist/witness/browser.js +644 -0
- package/dist/witness/browser.js.map +1 -0
- package/dist/witness/chaos.d.ts +179 -0
- package/dist/witness/chaos.d.ts.map +1 -0
- package/dist/witness/chaos.js +270 -0
- package/dist/witness/chaos.js.map +1 -0
- package/dist/witness/classifications.d.ts +42 -0
- package/dist/witness/classifications.d.ts.map +1 -0
- package/dist/witness/classifications.js +87 -0
- package/dist/witness/classifications.js.map +1 -0
- package/dist/witness/env-attestation.d.ts +98 -0
- package/dist/witness/env-attestation.d.ts.map +1 -0
- package/dist/witness/env-attestation.js +202 -0
- package/dist/witness/env-attestation.js.map +1 -0
- package/dist/witness/fixture-provider.d.ts +89 -0
- package/dist/witness/fixture-provider.d.ts.map +1 -0
- package/dist/witness/fixture-provider.js +116 -0
- package/dist/witness/fixture-provider.js.map +1 -0
- package/dist/witness/loopback-pins.d.ts +79 -0
- package/dist/witness/loopback-pins.d.ts.map +1 -0
- package/dist/witness/loopback-pins.js +244 -0
- package/dist/witness/loopback-pins.js.map +1 -0
- package/dist/witness/run-options.d.ts +47 -0
- package/dist/witness/run-options.d.ts.map +1 -0
- package/dist/witness/run-options.js +179 -0
- package/dist/witness/run-options.js.map +1 -0
- package/dist/witness/server.d.ts +34 -0
- package/dist/witness/server.d.ts.map +1 -0
- package/dist/witness/server.js +4963 -0
- package/dist/witness/server.js.map +1 -0
- package/dist/witness/task.d.ts +77 -0
- package/dist/witness/task.d.ts.map +1 -0
- package/dist/witness/task.js +201 -0
- package/dist/witness/task.js.map +1 -0
- package/dist/witness/twin-shapes.d.ts +51 -0
- package/dist/witness/twin-shapes.d.ts.map +1 -0
- package/dist/witness/twin-shapes.js +127 -0
- package/dist/witness/twin-shapes.js.map +1 -0
- package/dist/witness/types.d.ts +1094 -0
- package/dist/witness/types.d.ts.map +1 -0
- package/dist/witness/types.js +2 -0
- package/dist/witness/types.js.map +1 -0
- package/package.json +98 -4
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@gate-forge/witness/adapter-kit` — the configuration-first
|
|
3
|
+
* constructor for evidence adapters.
|
|
4
|
+
*
|
|
5
|
+
* A project writes a reviewed config (paths, wrapper keys, projected
|
|
6
|
+
* fields, paging, login seat) and gets a contract-valid adapter:
|
|
7
|
+
*
|
|
8
|
+
* ```js
|
|
9
|
+
* import { defineHttpAdapter } from '@gate-forge/witness/adapter-kit';
|
|
10
|
+
*
|
|
11
|
+
* export default defineHttpAdapter({
|
|
12
|
+
* resourceId: 'tenant.accounts',
|
|
13
|
+
* readPath: (id) => `/api/accounts/${encodeURIComponent(id)}`,
|
|
14
|
+
* listPath: '/api/accounts',
|
|
15
|
+
* collectionKey: 'accounts',
|
|
16
|
+
* paging: { kind: 'page', pageSize: 100 },
|
|
17
|
+
* fields: ['first_name', 'last_name', 'status'],
|
|
18
|
+
* deletion: 'archive',
|
|
19
|
+
* environmentFingerprint: 'loopback-v1',
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* The kit is a convenience, never a shortcut past the gate: what it
|
|
24
|
+
* returns is the frozen pin-#8 adapter, the gate grades a generated
|
|
25
|
+
* adapter exactly like a hand-written one, and a generated file is a
|
|
26
|
+
* STARTING POINT for review — `gateforge adapters scaffold` marks
|
|
27
|
+
* every guess and lists what still needs a human.
|
|
28
|
+
*/
|
|
29
|
+
export { defineHttpAdapter, DEFAULT_MAX_PAGES, DEFAULT_PAGE_SIZE } from './define.js';
|
|
30
|
+
export { firstArrayOf, readPath, projectEntity, } from './projection.js';
|
|
31
|
+
export { createSessionReader, KitAuthError, KitRedirectError, } from './session.js';
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapter-kit/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEtF,OAAO,EACL,YAAY,EACZ,QAAQ,EACR,aAAa,GAGd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,gBAAgB,GAKjB,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row projection: the shared, deterministic mapping from one raw
|
|
3
|
+
* response body onto the evidence shape `{ entityId, fields }`.
|
|
4
|
+
*
|
|
5
|
+
* Pure and total: an absent field is omitted (never invented as
|
|
6
|
+
* `null`), so a field the endpoint does not return can never be
|
|
7
|
+
* mistaken for a persisted value.
|
|
8
|
+
*/
|
|
9
|
+
/** The evidence shape every adapter's `normalize` returns. */
|
|
10
|
+
export interface NormalizedEntity {
|
|
11
|
+
/** The entity id, projected from the raw body. */
|
|
12
|
+
entityId: string;
|
|
13
|
+
/** Projected fields the obligation's `expectFields` can match. */
|
|
14
|
+
fields: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/** Projection inputs (the kit's field-shaped config). */
|
|
17
|
+
export interface ProjectionConfig {
|
|
18
|
+
/** Projected field names (dotted paths allowed). */
|
|
19
|
+
fields?: readonly string[];
|
|
20
|
+
/** Projected name -> key the response actually carries. */
|
|
21
|
+
fieldMap?: Readonly<Record<string, string>>;
|
|
22
|
+
/** Key identifying the entity (default `id`). */
|
|
23
|
+
entityIdKey?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Reads one dotted path out of a raw body.
|
|
27
|
+
*
|
|
28
|
+
* Args:
|
|
29
|
+
* source: the raw row.
|
|
30
|
+
* path: key, or dotted path (`owner.name`).
|
|
31
|
+
*
|
|
32
|
+
* Returns:
|
|
33
|
+
* unknown: the value at that path, or `undefined` when any segment is
|
|
34
|
+
* absent (an absent value is never an error here — the caller decides
|
|
35
|
+
* what an unknown field means).
|
|
36
|
+
*/
|
|
37
|
+
export declare function readPath(source: unknown, path: string): unknown;
|
|
38
|
+
/**
|
|
39
|
+
* Projects one raw row onto the evidence shape.
|
|
40
|
+
*
|
|
41
|
+
* Args:
|
|
42
|
+
* body: the raw response body.
|
|
43
|
+
* config: field-shaped kit config (`fields`, `fieldMap`, `entityIdKey`).
|
|
44
|
+
*
|
|
45
|
+
* Returns:
|
|
46
|
+
* NormalizedEntity: the entity id plus exactly the declared fields the
|
|
47
|
+
* row carries. A non-object body yields an empty projection.
|
|
48
|
+
*/
|
|
49
|
+
export declare function projectEntity(body: unknown, config: ProjectionConfig): NormalizedEntity;
|
|
50
|
+
/**
|
|
51
|
+
* A tolerant collection selector: the first array-valued property of a
|
|
52
|
+
* collection body, or the body itself when it already IS an array.
|
|
53
|
+
*
|
|
54
|
+
* A generated adapter uses it because the compiled graph knows WHICH
|
|
55
|
+
* collection route serves a resource, never the key the response wraps
|
|
56
|
+
* its rows in. It fails closed — a body with no array anywhere is an
|
|
57
|
+
* error the caller reports, not an empty list that would make every
|
|
58
|
+
* created row look absent — and every generated use is marked as a
|
|
59
|
+
* guess for the reviewer to replace with the exact key.
|
|
60
|
+
*
|
|
61
|
+
* Args:
|
|
62
|
+
* body: the parsed collection response body.
|
|
63
|
+
*
|
|
64
|
+
* Returns:
|
|
65
|
+
* unknown: the first array-valued property value, or the body itself
|
|
66
|
+
* when it is an array; undefined when neither is present.
|
|
67
|
+
*/
|
|
68
|
+
export declare function firstArrayOf(body: unknown): unknown;
|
|
69
|
+
//# sourceMappingURL=projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../../src/adapter-kit/projection.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5C,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAavF;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAOnD"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row projection: the shared, deterministic mapping from one raw
|
|
3
|
+
* response body onto the evidence shape `{ entityId, fields }`.
|
|
4
|
+
*
|
|
5
|
+
* Pure and total: an absent field is omitted (never invented as
|
|
6
|
+
* `null`), so a field the endpoint does not return can never be
|
|
7
|
+
* mistaken for a persisted value.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Reads one dotted path out of a raw body.
|
|
11
|
+
*
|
|
12
|
+
* Args:
|
|
13
|
+
* source: the raw row.
|
|
14
|
+
* path: key, or dotted path (`owner.name`).
|
|
15
|
+
*
|
|
16
|
+
* Returns:
|
|
17
|
+
* unknown: the value at that path, or `undefined` when any segment is
|
|
18
|
+
* absent (an absent value is never an error here — the caller decides
|
|
19
|
+
* what an unknown field means).
|
|
20
|
+
*/
|
|
21
|
+
export function readPath(source, path) {
|
|
22
|
+
let current = source;
|
|
23
|
+
for (const segment of path.split('.')) {
|
|
24
|
+
if (current === null || typeof current !== 'object')
|
|
25
|
+
return undefined;
|
|
26
|
+
current = current[segment];
|
|
27
|
+
}
|
|
28
|
+
return current;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Projects one raw row onto the evidence shape.
|
|
32
|
+
*
|
|
33
|
+
* Args:
|
|
34
|
+
* body: the raw response body.
|
|
35
|
+
* config: field-shaped kit config (`fields`, `fieldMap`, `entityIdKey`).
|
|
36
|
+
*
|
|
37
|
+
* Returns:
|
|
38
|
+
* NormalizedEntity: the entity id plus exactly the declared fields the
|
|
39
|
+
* row carries. A non-object body yields an empty projection.
|
|
40
|
+
*/
|
|
41
|
+
export function projectEntity(body, config) {
|
|
42
|
+
if (body === null || typeof body !== 'object') {
|
|
43
|
+
return { entityId: '', fields: {} };
|
|
44
|
+
}
|
|
45
|
+
const fields = {};
|
|
46
|
+
for (const key of config.fields ?? []) {
|
|
47
|
+
const sourceKey = config.fieldMap?.[key] ?? key;
|
|
48
|
+
const value = readPath(body, sourceKey);
|
|
49
|
+
if (value !== undefined)
|
|
50
|
+
fields[key] = value;
|
|
51
|
+
}
|
|
52
|
+
const idKey = config.entityIdKey ?? 'id';
|
|
53
|
+
const rawId = readPath(body, idKey);
|
|
54
|
+
return { entityId: rawId === undefined || rawId === null ? '' : String(rawId), fields };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A tolerant collection selector: the first array-valued property of a
|
|
58
|
+
* collection body, or the body itself when it already IS an array.
|
|
59
|
+
*
|
|
60
|
+
* A generated adapter uses it because the compiled graph knows WHICH
|
|
61
|
+
* collection route serves a resource, never the key the response wraps
|
|
62
|
+
* its rows in. It fails closed — a body with no array anywhere is an
|
|
63
|
+
* error the caller reports, not an empty list that would make every
|
|
64
|
+
* created row look absent — and every generated use is marked as a
|
|
65
|
+
* guess for the reviewer to replace with the exact key.
|
|
66
|
+
*
|
|
67
|
+
* Args:
|
|
68
|
+
* body: the parsed collection response body.
|
|
69
|
+
*
|
|
70
|
+
* Returns:
|
|
71
|
+
* unknown: the first array-valued property value, or the body itself
|
|
72
|
+
* when it is an array; undefined when neither is present.
|
|
73
|
+
*/
|
|
74
|
+
export function firstArrayOf(body) {
|
|
75
|
+
if (Array.isArray(body))
|
|
76
|
+
return body;
|
|
77
|
+
if (body === null || typeof body !== 'object')
|
|
78
|
+
return undefined;
|
|
79
|
+
for (const value of Object.values(body)) {
|
|
80
|
+
if (Array.isArray(value))
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../../src/adapter-kit/projection.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CAAC,MAAe,EAAE,IAAY;IACpD,IAAI,OAAO,GAAY,MAAM,CAAC;IAC9B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACtE,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,IAAa,EAAE,MAAwB;IACnE,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACtC,CAAC;IACD,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;QAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACxC,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/C,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACpC,OAAO,EAAE,QAAQ,EAAE,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAC1F,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAA+B,CAAC,EAAE,CAAC;QACnE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;IACzC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Witness-side authenticated session for kit adapters.
|
|
3
|
+
*
|
|
4
|
+
* Credentials live in the WITNESS process environment and nowhere else:
|
|
5
|
+
* every seat names its env vars in the adapter config, the values are
|
|
6
|
+
* read at call time, and nothing here logs, prints, or returns them. A
|
|
7
|
+
* seat performs exactly one login POST (the same request a human
|
|
8
|
+
* browser performs) and then issues GET-only evidence reads with the
|
|
9
|
+
* session it obtained; a read rejected with 401 triggers ONE re-login
|
|
10
|
+
* and one retry, never a loop.
|
|
11
|
+
*
|
|
12
|
+
* This module can authenticate and read. It cannot create, update, or
|
|
13
|
+
* delete business state — no method here issues anything but the
|
|
14
|
+
* declared login POST and GETs.
|
|
15
|
+
*/
|
|
16
|
+
import type { HttpAdapterAuth } from './config.js';
|
|
17
|
+
import type { SessionIdentity } from '../witness/types.js';
|
|
18
|
+
/** One cached seat session (per base URL). */
|
|
19
|
+
interface SeatSession {
|
|
20
|
+
/** Credential header value, or null while not logged in. */
|
|
21
|
+
authorization: string | null;
|
|
22
|
+
/** Cookie header value, or null while not logged in. */
|
|
23
|
+
cookie: string | null;
|
|
24
|
+
}
|
|
25
|
+
/** Sessions keyed by `<baseUrl>|<seat>`, shared by every read of one kit adapter. */
|
|
26
|
+
export type SessionStore = Map<string, SeatSession>;
|
|
27
|
+
/** The result of one kit-issued GET. */
|
|
28
|
+
export interface KitGetResult {
|
|
29
|
+
/** HTTP status. */
|
|
30
|
+
status: number;
|
|
31
|
+
/** Response headers (fingerprint marker lives here). */
|
|
32
|
+
headers: Headers;
|
|
33
|
+
/** Parsed JSON body, or undefined for a non-JSON body. */
|
|
34
|
+
body: unknown;
|
|
35
|
+
}
|
|
36
|
+
/** What one probe read showed, as the kit's own read path saw it. */
|
|
37
|
+
export interface KitProbeResult {
|
|
38
|
+
/** The exact path the read GET hit. */
|
|
39
|
+
path: string;
|
|
40
|
+
/** HTTP status of that GET. */
|
|
41
|
+
status: number;
|
|
42
|
+
/** Response headers (the environment marker lives here). */
|
|
43
|
+
headers: Headers;
|
|
44
|
+
}
|
|
45
|
+
/** The witness env vars a seat failure is about (names, never values). */
|
|
46
|
+
export interface KitAuthFailure {
|
|
47
|
+
/** The seat that could not authenticate. */
|
|
48
|
+
seat: string;
|
|
49
|
+
/** Env var names the seat needs, or null when the login was rejected. */
|
|
50
|
+
envVars: readonly string[] | null;
|
|
51
|
+
}
|
|
52
|
+
/** Raised when the witness environment does not carry a credential. */
|
|
53
|
+
export declare class KitAuthError extends Error {
|
|
54
|
+
/** Which seat failed, and which env vars it needs (null: rejected login). */
|
|
55
|
+
readonly failure: KitAuthFailure | null;
|
|
56
|
+
/**
|
|
57
|
+
* Builds one auth failure.
|
|
58
|
+
*
|
|
59
|
+
* Args:
|
|
60
|
+
* message: the plain message a witnessed run shows.
|
|
61
|
+
* failure: the structured facts a probe reports, when it has them.
|
|
62
|
+
*/
|
|
63
|
+
constructor(message: string, failure?: KitAuthFailure | null);
|
|
64
|
+
}
|
|
65
|
+
/** Raised when a read only succeeds through a redirect. */
|
|
66
|
+
export declare class KitRedirectError extends Error {
|
|
67
|
+
constructor(message: string);
|
|
68
|
+
}
|
|
69
|
+
/** The kit's per-adapter read transport. */
|
|
70
|
+
export interface SessionReaderOptions {
|
|
71
|
+
/** The adapter's declared auth (default: none). */
|
|
72
|
+
auth?: HttpAdapterAuth;
|
|
73
|
+
/** Registry identity, for diagnostics. */
|
|
74
|
+
resourceId: string;
|
|
75
|
+
/**
|
|
76
|
+
* The witness-adapter context the read runs under, carrying the
|
|
77
|
+
* session the read belongs to and the identity THAT session
|
|
78
|
+
* registered (plan Phase 4b item 3b).
|
|
79
|
+
*/
|
|
80
|
+
ctx: {
|
|
81
|
+
baseUrl: string;
|
|
82
|
+
headers?: Record<string, string>;
|
|
83
|
+
sessionId?: string;
|
|
84
|
+
sessionIdentity?: SessionIdentity | null;
|
|
85
|
+
};
|
|
86
|
+
/** Per-request timeout in ms (default 10000). */
|
|
87
|
+
timeoutMs?: number;
|
|
88
|
+
/** Session store shared across reads (one login, then reused). */
|
|
89
|
+
sessions?: SessionStore;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Builds the kit's GET transport for one adapter invocation.
|
|
93
|
+
*
|
|
94
|
+
* Args:
|
|
95
|
+
* options: declared auth, resource id, and the witness context.
|
|
96
|
+
*
|
|
97
|
+
* Returns:
|
|
98
|
+
* (path: string) => Promise<KitGetResult>: one read, login included.
|
|
99
|
+
* @throws KitAuthError on missing/rejected credentials; KitRedirectError
|
|
100
|
+
* when the app answers the read with a redirect (a read that only
|
|
101
|
+
* works through a redirect is never a stable evidence path).
|
|
102
|
+
*/
|
|
103
|
+
export declare function createSessionReader(options: SessionReaderOptions): (path: string) => Promise<KitGetResult>;
|
|
104
|
+
export {};
|
|
105
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/adapter-kit/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAA+B,eAAe,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,8CAA8C;AAC9C,UAAU,WAAW;IACnB,4DAA4D;IAC5D,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,wDAAwD;IACxD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAmBD,qFAAqF;AACrF,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEpD,wCAAwC;AACxC,MAAM,WAAW,YAAY;IAC3B,mBAAmB;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,IAAI,EAAE,OAAO,CAAC;CACf;AAED,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,0EAA0E;AAC1E,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACnC;AAED,uEAAuE;AACvE,qBAAa,YAAa,SAAQ,KAAK;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAExC;;;;;;OAMG;gBACS,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,cAAc,GAAG,IAAW;CAKnE;AAED,2DAA2D;AAC3D,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AA8JD,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,0CAA0C;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,GAAG,EAAE;QACH,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;KAC1C,CAAC;IACF,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAwE1G"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/** Raised when the witness environment does not carry a credential. */
|
|
2
|
+
export class KitAuthError extends Error {
|
|
3
|
+
/** Which seat failed, and which env vars it needs (null: rejected login). */
|
|
4
|
+
failure;
|
|
5
|
+
/**
|
|
6
|
+
* Builds one auth failure.
|
|
7
|
+
*
|
|
8
|
+
* Args:
|
|
9
|
+
* message: the plain message a witnessed run shows.
|
|
10
|
+
* failure: the structured facts a probe reports, when it has them.
|
|
11
|
+
*/
|
|
12
|
+
constructor(message, failure = null) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'KitAuthError';
|
|
15
|
+
this.failure = failure;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Raised when a read only succeeds through a redirect. */
|
|
19
|
+
export class KitRedirectError extends Error {
|
|
20
|
+
constructor(message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'KitRedirectError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the seat one read authenticates with: the identity THIS
|
|
27
|
+
* session registered (plan Phase 4b item 3b) when it names a declared
|
|
28
|
+
* seat, else the adapter's configured seat with the process-global
|
|
29
|
+
* environment credentials — today's behavior, byte-identical when no
|
|
30
|
+
* identity is registered.
|
|
31
|
+
*
|
|
32
|
+
* Args:
|
|
33
|
+
* auth: the adapter's declared auth.
|
|
34
|
+
* identity: the reading session's registered identity, or null.
|
|
35
|
+
*
|
|
36
|
+
* Returns:
|
|
37
|
+
* ResolvedSeat | null: the seat plus its credential source, or null
|
|
38
|
+
* for `kind: 'none'`.
|
|
39
|
+
* @throws KitAuthError when the named seat does not exist, or when an
|
|
40
|
+
* identity names a seat this adapter does not declare.
|
|
41
|
+
*/
|
|
42
|
+
function resolveSeat(auth, identity) {
|
|
43
|
+
if (auth.kind === 'none')
|
|
44
|
+
return null;
|
|
45
|
+
const seats = auth.seats;
|
|
46
|
+
if (identity !== null && seats[identity.seat] === undefined) {
|
|
47
|
+
throw new KitAuthError(`session identity seat '${identity.seat}' is not declared by this adapter (available: ` +
|
|
48
|
+
`${Object.keys(seats).sort().join(', ')})`);
|
|
49
|
+
}
|
|
50
|
+
// The registered identity WINS for the seat it names; every other seat
|
|
51
|
+
// keeps reading through the process-global environment.
|
|
52
|
+
const name = identity?.seat ?? auth.seat ?? Object.keys(seats)[0];
|
|
53
|
+
if (name === undefined) {
|
|
54
|
+
throw new KitAuthError('auth declares no seats: add a named seat (credentials are read from the witness environment)');
|
|
55
|
+
}
|
|
56
|
+
const seat = seats[name];
|
|
57
|
+
if (seat === undefined) {
|
|
58
|
+
throw new KitAuthError(`auth seat '${name}' is not declared (available: ${Object.keys(seats).sort().join(', ')})`);
|
|
59
|
+
}
|
|
60
|
+
// Credential source: the session's own values for the seat it named,
|
|
61
|
+
// else the witness process environment.
|
|
62
|
+
const values = identity !== null && identity.seat === name ? identity.values : null;
|
|
63
|
+
if (auth.kind === 'bearer') {
|
|
64
|
+
const bearer = seat;
|
|
65
|
+
if (typeof bearer.tokenEnv !== 'string') {
|
|
66
|
+
throw new KitAuthError(`auth seat '${name}' must declare tokenEnv (a witness env var)`);
|
|
67
|
+
}
|
|
68
|
+
return { kind: 'bearer', name, bearer, values };
|
|
69
|
+
}
|
|
70
|
+
const login = seat;
|
|
71
|
+
if (typeof login.loginPath !== 'string' || typeof login.credentials !== 'object') {
|
|
72
|
+
throw new KitAuthError(`auth seat '${name}' must declare loginPath and credentials (field -> witness env var)`);
|
|
73
|
+
}
|
|
74
|
+
return { kind: 'cookie-login', name, login, values };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The credential header one GET carries, logging in first when needed.
|
|
78
|
+
*
|
|
79
|
+
* The values come from the session's REGISTERED identity when it named
|
|
80
|
+
* this seat (every declared variable must be present — a partial
|
|
81
|
+
* identity fails closed instead of completing itself from the
|
|
82
|
+
* process-global seat), otherwise from the witness process environment
|
|
83
|
+
* exactly as before. Either way a diagnostic names the variables, never
|
|
84
|
+
* their values.
|
|
85
|
+
*
|
|
86
|
+
* Args:
|
|
87
|
+
* seat: the resolved seat.
|
|
88
|
+
* seatKey: session cache key.
|
|
89
|
+
* baseUrl: the adapter base the read targets.
|
|
90
|
+
* sessions: this kit's session store.
|
|
91
|
+
*
|
|
92
|
+
* Returns:
|
|
93
|
+
* Promise<Record<string, string>>: headers to merge into the read.
|
|
94
|
+
* @throws KitAuthError when credentials are absent or login is rejected.
|
|
95
|
+
*/
|
|
96
|
+
async function credentialHeaders(seat, seatKey, baseUrl, sessions) {
|
|
97
|
+
// Credentials are read from the witness process environment, never
|
|
98
|
+
// from the repo, argv, or the suite — and a seat that cannot be
|
|
99
|
+
// satisfied is named by its env vars, never by a bare 401 later.
|
|
100
|
+
const config = seat.kind === 'bearer' ? seat.bearer : seat.login;
|
|
101
|
+
const envVars = 'tokenEnv' in config ? [config.tokenEnv] : Object.values(config.credentials);
|
|
102
|
+
const identity = seat.values;
|
|
103
|
+
const valueOf = (name) => (identity === null ? undefined : identity[name]) ?? process.env[name];
|
|
104
|
+
const missing = envVars.filter((name) => {
|
|
105
|
+
const value = valueOf(name);
|
|
106
|
+
return value === undefined || value === '';
|
|
107
|
+
});
|
|
108
|
+
if (missing.length > 0) {
|
|
109
|
+
throw new KitAuthError(identity === null
|
|
110
|
+
? `adapter seat '${seat.name}' needs ${missing.join(', ')} in the WITNESS process ` +
|
|
111
|
+
'environment (never in the repo, argv, or the suite)'
|
|
112
|
+
: `session identity for seat '${seat.name}' is missing ${missing.join(', ')}: a ` +
|
|
113
|
+
'registered identity must carry EVERY credential the seat declares', { seat: seat.name, envVars: missing });
|
|
114
|
+
}
|
|
115
|
+
if ('tokenEnv' in config) {
|
|
116
|
+
const scheme = config.scheme ?? 'Bearer';
|
|
117
|
+
return { authorization: `${scheme} ${String(valueOf(config.tokenEnv))}` };
|
|
118
|
+
}
|
|
119
|
+
const login = config;
|
|
120
|
+
const cached = sessions.get(seatKey);
|
|
121
|
+
if (cached?.cookie != null)
|
|
122
|
+
return { cookie: cached.cookie };
|
|
123
|
+
const body = {};
|
|
124
|
+
for (const [field, envVar] of Object.entries(login.credentials)) {
|
|
125
|
+
body[field] = String(valueOf(envVar));
|
|
126
|
+
}
|
|
127
|
+
const response = await fetch(`${baseUrl}${login.loginPath}`, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
headers: {
|
|
130
|
+
accept: 'application/json',
|
|
131
|
+
'content-type': 'application/json',
|
|
132
|
+
...(login.headers ?? {}),
|
|
133
|
+
},
|
|
134
|
+
body: JSON.stringify(body),
|
|
135
|
+
});
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
throw new KitAuthError(`adapter seat '${seat.name}' login failed: POST ${login.loginPath} -> ${String(response.status)}`);
|
|
138
|
+
}
|
|
139
|
+
const cookies = typeof response.headers.getSetCookie === 'function'
|
|
140
|
+
? response.headers.getSetCookie()
|
|
141
|
+
: [response.headers.get('set-cookie') ?? ''];
|
|
142
|
+
const pairs = cookies
|
|
143
|
+
.flatMap((header) => header.split(/,(?=\s*[^;=]+=[^;]*)/))
|
|
144
|
+
.map((header) => header.split(';')[0]?.trim() ?? '')
|
|
145
|
+
.filter((pair) => pair.includes('='));
|
|
146
|
+
const wanted = pairs.filter((pair) => {
|
|
147
|
+
const name = pair.slice(0, pair.indexOf('='));
|
|
148
|
+
return login.cookieName === undefined || name === login.cookieName;
|
|
149
|
+
});
|
|
150
|
+
if (wanted.length === 0) {
|
|
151
|
+
throw new KitAuthError(`adapter seat '${seat.name}' login set no ${login.cookieName === undefined ? '' : `'${login.cookieName}' `}cookie`);
|
|
152
|
+
}
|
|
153
|
+
const cookie = wanted.join('; ');
|
|
154
|
+
sessions.set(seatKey, { authorization: null, cookie });
|
|
155
|
+
return { cookie };
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Builds the kit's GET transport for one adapter invocation.
|
|
159
|
+
*
|
|
160
|
+
* Args:
|
|
161
|
+
* options: declared auth, resource id, and the witness context.
|
|
162
|
+
*
|
|
163
|
+
* Returns:
|
|
164
|
+
* (path: string) => Promise<KitGetResult>: one read, login included.
|
|
165
|
+
* @throws KitAuthError on missing/rejected credentials; KitRedirectError
|
|
166
|
+
* when the app answers the read with a redirect (a read that only
|
|
167
|
+
* works through a redirect is never a stable evidence path).
|
|
168
|
+
*/
|
|
169
|
+
export function createSessionReader(options) {
|
|
170
|
+
const { auth, resourceId, ctx } = options;
|
|
171
|
+
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
172
|
+
const baseUrl = ctx.baseUrl.replace(/\/$/, '');
|
|
173
|
+
const identity = ctx.sessionIdentity ?? null;
|
|
174
|
+
const seat = auth === undefined || auth.kind === 'none' ? null : resolveSeat(auth, identity);
|
|
175
|
+
// The cache key carries the seat AND the session it was read under: a
|
|
176
|
+
// cookie logged in as one session's identity is never served to
|
|
177
|
+
// another session's read, even through the same adapter instance.
|
|
178
|
+
const seatKey = `${baseUrl}|${seat?.name ?? ''}|${identity === null ? 'env' : `session:${ctx.sessionId ?? 'unattributed'}`}`;
|
|
179
|
+
// One store per kit adapter: the first read logs in, later reads
|
|
180
|
+
// reuse the session until the app rejects it with 401.
|
|
181
|
+
const sessions = options.sessions ?? new Map();
|
|
182
|
+
/**
|
|
183
|
+
* Issues one GET and parses its JSON body.
|
|
184
|
+
*
|
|
185
|
+
* Args:
|
|
186
|
+
* path: absolute path (with query) to read.
|
|
187
|
+
* credential: credential headers to attach.
|
|
188
|
+
*
|
|
189
|
+
* Returns:
|
|
190
|
+
* Promise<KitGetResult>: status, headers, parsed body.
|
|
191
|
+
* @throws KitRedirectError when the app answers with a redirect.
|
|
192
|
+
*/
|
|
193
|
+
const getOnce = async (path, credential) => {
|
|
194
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
195
|
+
// A read that only works through a redirect is not a stable
|
|
196
|
+
// evidence path: never follow one silently (E28).
|
|
197
|
+
redirect: 'manual',
|
|
198
|
+
headers: {
|
|
199
|
+
accept: 'application/json',
|
|
200
|
+
...(ctx.headers ?? {}),
|
|
201
|
+
...credential,
|
|
202
|
+
},
|
|
203
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
204
|
+
});
|
|
205
|
+
const body = await response
|
|
206
|
+
.json()
|
|
207
|
+
.catch(() => undefined);
|
|
208
|
+
if (response.status >= 300 && response.status < 400) {
|
|
209
|
+
const location = response.headers.get('location');
|
|
210
|
+
throw new KitRedirectError(`${resourceId}: GET ${path} answered ${String(response.status)}${location === null ? '' : ` -> ${location}`}; a read that only works through a redirect is not a stable evidence path — point ` +
|
|
211
|
+
'readPath/listPath at the path the app finally serves');
|
|
212
|
+
}
|
|
213
|
+
return { status: response.status, headers: response.headers, body };
|
|
214
|
+
};
|
|
215
|
+
if (seat === null) {
|
|
216
|
+
return async (path) => getOnce(path, {});
|
|
217
|
+
}
|
|
218
|
+
return async (path) => {
|
|
219
|
+
let credential = await credentialHeaders(seat, seatKey, baseUrl, sessions);
|
|
220
|
+
let result = await getOnce(path, credential);
|
|
221
|
+
if (result.status === 401) {
|
|
222
|
+
// One re-login, one retry: an expired session must not become a loop.
|
|
223
|
+
sessions.delete(seatKey);
|
|
224
|
+
credential = await credentialHeaders(seat, seatKey, baseUrl, sessions);
|
|
225
|
+
result = await getOnce(path, credential);
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/adapter-kit/session.ts"],"names":[],"mappings":"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"}
|