sessionpipe-core 0.1.1 → 0.3.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.
@@ -0,0 +1,171 @@
1
+ /** One passkey tap vouches for a day key for at most this long. */
2
+ export declare const GRANT_MAX_MS: number;
3
+ /** Clock slack between the signing device, the receiver and the machine. */
4
+ export declare const SKEW_MS: number;
5
+ /** The machine judges a command by when it was SIGNED: a message sent while the lid
6
+ * was shut still runs when the machine wakes, up to a day later. */
7
+ export declare const MACHINE_MAX_AGE_MS: number;
8
+ /** A receiver's early check is stricter: a command is carried within ten minutes of
9
+ * being signed, or not at all. */
10
+ export declare const RECEIVER_MAX_AGE_MS: number;
11
+ /** How long a machine remembers a nonce: longer than MACHINE_MAX_AGE_MS + SKEW_MS. */
12
+ export declare const NONCE_TTL_MS: number;
13
+ /** The whole command string, in UTF-16 code units (what JSON.parse sees). */
14
+ export declare const CMD_MAX = 12000;
15
+ /** A prompt's text, in characters. */
16
+ export declare const TEXT_MAX = 4000;
17
+ /** A permission answer's note. */
18
+ export declare const NOTE_MAX = 2000;
19
+ /** A grant string. */
20
+ export declare const GRANT_STR_MAX = 2000;
21
+ export declare const COMMAND_TYPE = "sessionpipe.control";
22
+ export declare const GRANT_TYPE = "sessionpipe.grant";
23
+ export declare const CONTROL_KINDS: readonly ["prompt", "permission.answer", "cancel", "start"];
24
+ export type ControlKind = (typeof CONTROL_KINDS)[number];
25
+ /** COSE algorithm ids a trusted key may use. */
26
+ export declare const ES256 = -7;
27
+ export declare const RS256 = -257;
28
+ /** A key enrolled on the machine: a passkey's credential id, COSE alg and SPKI (base64url). */
29
+ export interface TrustedKey {
30
+ id: string;
31
+ alg: number;
32
+ spki: string;
33
+ }
34
+ /** A WebAuthn assertion: credential id, authenticatorData, clientDataJSON, signature (base64url). */
35
+ export interface Assertion {
36
+ cred: string;
37
+ ad: string;
38
+ cd: string;
39
+ sig: string;
40
+ }
41
+ /** The day's grant: a passkey's assertion over sha256(str), where str names the day key. */
42
+ export interface GrantBundle extends Assertion {
43
+ str: string;
44
+ }
45
+ /** What a receiver carries for one command (control.json minus the receiver's envelope). */
46
+ export interface SignedCommand {
47
+ cmd: string;
48
+ csig?: string | null;
49
+ grant?: GrantBundle | null;
50
+ confirm?: Assertion | null;
51
+ }
52
+ export interface Grant {
53
+ v: 1;
54
+ t: typeof GRANT_TYPE;
55
+ pub: string;
56
+ iat: number;
57
+ exp: number;
58
+ rp: string;
59
+ }
60
+ export interface ControlCommand {
61
+ v: 1;
62
+ t: typeof COMMAND_TYPE;
63
+ machine: string;
64
+ kind: ControlKind;
65
+ /** `<harness>:<id>`, e.g. `claude-code:8c132906-…`. */
66
+ session: string;
67
+ text?: string;
68
+ for?: string;
69
+ decision?: "allow" | "deny";
70
+ note?: string;
71
+ cwd?: string;
72
+ nonce: string;
73
+ iat: number;
74
+ }
75
+ /** Why a command was refused. Stable: conformance vectors and acks name these. */
76
+ export type RefusalCode = "malformed" | "not_a_command" | "wrong_machine" | "unknown_kind" | "bad_session" | "bad_fields" | "bad_nonce" | "too_old" | "future" | "unsigned" | "untrusted_key" | "bad_assertion" | "bad_grant" | "outside_grant" | "bad_csig" | "replay" | "nonce_store";
77
+ export type Verdict = {
78
+ ok: true;
79
+ cmd: ControlCommand;
80
+ via: "grant" | "confirm";
81
+ key: string;
82
+ } | {
83
+ ok: false;
84
+ code: RefusalCode;
85
+ why: string;
86
+ };
87
+ export interface VerifyOptions {
88
+ /** This machine's id; a command for another machine is refused. */
89
+ machine: string;
90
+ /** The receiver's WebAuthn rp id the keys were enrolled for (well-known control.signing.rp_id). */
91
+ rpId: string;
92
+ /** The keys enrolled on this machine (or, for a receiver's early check, the account's). */
93
+ trusted: TrustedKey[];
94
+ /** Epoch ms. */
95
+ now: number;
96
+ /** MACHINE_MAX_AGE_MS on a machine (default), RECEIVER_MAX_AGE_MS on a receiver. */
97
+ maxAgeMs?: number;
98
+ /** Called once, last, only for a command whose signatures all verified: answer
99
+ * true when the nonce was seen before, otherwise record it (durably) and answer
100
+ * false. A throw refuses the command (`nonce_store`): never run what could not
101
+ * be remembered. Omit it on a receiver's early check. */
102
+ seenNonce?: (nonce: string) => boolean | Promise<boolean>;
103
+ }
104
+ export declare function b64url(bytes: Uint8Array | ArrayBuffer): string;
105
+ /** base64url without padding, strictly; null for anything else. */
106
+ export declare function fromB64url(s: unknown): Uint8Array | null;
107
+ export declare function sha256(data: string | Uint8Array): Promise<Uint8Array>;
108
+ /** A DER ECDSA signature (what WebAuthn returns) as the 64-byte r‖s WebCrypto verifies.
109
+ * Strict: every length must match the bytes, so one signature has one encoding (a
110
+ * P-256 signature is at most 72 bytes, so the short length form is the only one). */
111
+ export declare function derToRaw(der: Uint8Array): Uint8Array | null;
112
+ /** Can this key be enrolled at all? A machine refuses to trust a key it could never verify with. */
113
+ export declare function keyUsable(key: TrustedKey): Promise<boolean>;
114
+ /** A WebAuthn origin a key may have been used from: https on the rp id or a subdomain;
115
+ * for rp id `localhost`, plain http on any port too. A bare origin, as a browser writes it. */
116
+ export declare function originAllowed(origin: unknown, rpId: string): boolean;
117
+ type Check = {
118
+ ok: true;
119
+ } | {
120
+ ok: false;
121
+ why: string;
122
+ };
123
+ /** One passkey assertion over `challenge`, made with `key`, by a verified person. */
124
+ export declare function verifyAssertion(challenge: Uint8Array, a: Assertion | null | undefined, key: TrustedKey, rpId: string): Promise<Check>;
125
+ /** What a passkey signs to enroll on a machine: bound to that machine and that pairing code. */
126
+ export declare function pairChallenge(machine: string, code: string): Promise<Uint8Array>;
127
+ /** The enrollment proof: the new key's assertion over pairChallenge(machine, code).
128
+ * Only after this verifies does the key go into the machine's trust store. */
129
+ export declare function verifyEnrollment(o: {
130
+ machine: string;
131
+ code: string;
132
+ key: TrustedKey;
133
+ proof: Assertion;
134
+ rpId: string;
135
+ }): Promise<Check>;
136
+ type Parsed = {
137
+ ok: true;
138
+ cmd: ControlCommand;
139
+ } | {
140
+ ok: false;
141
+ code: RefusalCode;
142
+ why: string;
143
+ };
144
+ /** The session id rule per harness (ADAPTERS.md): Claude Code ids are UUIDs. */
145
+ export declare function sessionIdOk(harness: string, id: string): boolean;
146
+ /** Split `<harness>:<id>`; null when either half breaks its rule. */
147
+ export declare function parseSessionRef(ref: unknown): {
148
+ harness: string;
149
+ id: string;
150
+ } | null;
151
+ /** Read the command's fields from the exact string. Structure only; no clock, no keys. */
152
+ export declare function parseCommand(str: unknown): Parsed;
153
+ /** The grant's fields, read from its exact string. */
154
+ export declare function parseGrant(str: unknown, rpId: string): {
155
+ ok: true;
156
+ grant: Grant;
157
+ } | {
158
+ ok: false;
159
+ why: string;
160
+ };
161
+ /**
162
+ * Is this a command this machine may run? The checks, in the spec's order
163
+ * (CONTROL.md §5): the exact bytes parse; the command is for this machine; it is
164
+ * signed — a grant from a trusted key plus the day key's signature, or a confirm
165
+ * over sha256(cmd); it was signed within the age window; its nonce is new.
166
+ * The folder and open-attention checks that follow are the daemon's (they read
167
+ * the machine, not the command).
168
+ */
169
+ export declare function verifyCommand(s: SignedCommand | null | undefined, o: VerifyOptions): Promise<Verdict>;
170
+ export {};
171
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../../src/control/verify.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sessionpipe-core",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "sessionpipe core: protocol types, harness adapters, privacy filter and redaction rulesets, outbox and sinks. Zero runtime dependencies. (published unscoped until the @sessionpipe npm org exists; the code is the same)",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -39,6 +39,10 @@
39
39
  "./schema": {
40
40
  "types": "./dist/schema/v1.d.ts",
41
41
  "import": "./dist/schema.js"
42
+ },
43
+ "./control": {
44
+ "types": "./dist/src/control/index.d.ts",
45
+ "import": "./dist/control.js"
42
46
  }
43
47
  },
44
48
  "types": "./dist/src/index.d.ts",