@byok-sdk/core 0.2.0 → 0.4.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/dist/attestation.d.ts +7 -0
- package/dist/blob.d.ts +42 -1
- package/dist/device-assertion.d.ts +224 -0
- package/dist/errors.d.ts +4 -0
- package/dist/in-memory/index.d.ts +1 -0
- package/dist/in-memory/skill-pack.d.ts +25 -0
- package/dist/index.d.ts +11 -6
- package/dist/index.js +525 -41
- package/dist/index.js.map +1 -1
- package/dist/mailbox.d.ts +14 -2
- package/dist/pairing.d.ts +38 -0
- package/dist/ports-contract.d.ts +18 -1
- package/dist/presence.d.ts +8 -0
- package/dist/skill-pack.d.ts +251 -0
- package/dist/stores.d.ts +10 -1
- package/package.json +1 -1
package/dist/attestation.d.ts
CHANGED
|
@@ -38,6 +38,13 @@ export declare const DEVICE_PROOF_VERSION = 1;
|
|
|
38
38
|
/** Signature algorithms this envelope version admits. */
|
|
39
39
|
export declare const DEVICE_PROOF_ALGORITHMS: readonly ['ed25519'];
|
|
40
40
|
export type DeviceProofAlgorithm = (typeof DEVICE_PROOF_ALGORITHMS)[number];
|
|
41
|
+
/**
|
|
42
|
+
* HTTP header carrying the base64url device-proof envelope on a truth-route
|
|
43
|
+
* request (§12.6.3). Both the daemon that mints the proof and the host that
|
|
44
|
+
* decodes it must name the exact same header, so it is a single wire constant
|
|
45
|
+
* here rather than a string re-spelled on each side.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEVICE_PROOF_HEADER = "x-byok-device-proof";
|
|
41
48
|
export type JsonPrimitive = string | number | boolean | null;
|
|
42
49
|
export type JsonValue = JsonPrimitive | readonly JsonValue[] | {
|
|
43
50
|
readonly [key: string]: JsonValue;
|
package/dist/blob.d.ts
CHANGED
|
@@ -17,11 +17,52 @@ export type ContentHash = string & {
|
|
|
17
17
|
export declare function contentHash(value: string): ContentHash;
|
|
18
18
|
/** Non-throwing form of {@link contentHash}. */
|
|
19
19
|
export declare function isContentHash(value: unknown): value is ContentHash;
|
|
20
|
+
/**
|
|
21
|
+
* What a deployment-level key namespace may look like: slash-joined segments of
|
|
22
|
+
* lowercase alphanumerics, `.`, `_`, and `-`, each starting with an
|
|
23
|
+
* alphanumeric. No leading or trailing slash, and therefore no empty segment.
|
|
24
|
+
*
|
|
25
|
+
* Narrow on purpose, and narrower than S3 keys allow. A prefix is spliced into
|
|
26
|
+
* every key this SDK ever writes, so the only prefixes worth accepting are the
|
|
27
|
+
* ones that reach the object store spelled exactly as configured: anything
|
|
28
|
+
* requiring percent-encoding would give the deployment's objects two names, and
|
|
29
|
+
* anything with an empty segment would make `a//b` and `a/b` the same key at
|
|
30
|
+
* rest but different strings in config. Case is folded out for the same reason
|
|
31
|
+
* {@link contentHash} refuses uppercase hex — one address, one spelling.
|
|
32
|
+
*/
|
|
33
|
+
export declare const OBJECT_KEY_PREFIX_PATTERN: RegExp;
|
|
34
|
+
/** A validated deployment key namespace. Branded, so only the mint point below can produce one. */
|
|
35
|
+
export type ObjectKeyPrefix = string & {
|
|
36
|
+
readonly __byokObjectKeyPrefix: unique symbol;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* The single mint point for {@link ObjectKeyPrefix}.
|
|
40
|
+
*
|
|
41
|
+
* There is no "empty means no prefix" spelling here: a composition that has no
|
|
42
|
+
* prefix omits the option, and one that passes `''` has misconfigured something
|
|
43
|
+
* (an unset environment variable is the usual way). Accepting it silently would
|
|
44
|
+
* make the two indistinguishable at exactly the moment the difference decides
|
|
45
|
+
* where a deployment's objects live.
|
|
46
|
+
*
|
|
47
|
+
* @throws {ByokCoreError} code `object_key_prefix_invalid`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function objectKeyPrefix(value: string): ObjectKeyPrefix;
|
|
20
50
|
/**
|
|
21
51
|
* Tenant-scoped object key, e.g.
|
|
22
52
|
* `tenants/<tenantId>/objects/sha256/<hex>` (§12.7.4).
|
|
53
|
+
*
|
|
54
|
+
* `prefix` namespaces the whole layout — `<prefix>/tenants/...` — so one bucket
|
|
55
|
+
* can hold several deployments without either of them owning the bucket root.
|
|
56
|
+
* Omitting it produces the unprefixed key verbatim, which is what makes the
|
|
57
|
+
* option safe to add: every object already at rest was written without one.
|
|
58
|
+
*
|
|
59
|
+
* The prefix is an IMMUTABLE property of a deployment. It is spliced in here
|
|
60
|
+
* and nowhere else, and nothing reads a key back under a second layout: change
|
|
61
|
+
* a live deployment's prefix and its existing objects become unaddressable.
|
|
62
|
+
* See `R2BlobStoreOptions.keyPrefix` in `@byok-sdk/cloud-dataplane` for the full
|
|
63
|
+
* operational contract.
|
|
23
64
|
*/
|
|
24
|
-
export declare function tenantObjectKey(tenant: TenantId, hash: ContentHash): string;
|
|
65
|
+
export declare function tenantObjectKey(tenant: TenantId, hash: ContentHash, prefix?: ObjectKeyPrefix): string;
|
|
25
66
|
/**
|
|
26
67
|
* Object manifest lifecycle (§12.7.8).
|
|
27
68
|
*
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device assertion envelope, canonical signing bytes, and verifier
|
|
3
|
+
* (plan `device-assertion-broker`, P3 ①-⑤).
|
|
4
|
+
*
|
|
5
|
+
* A device assertion is a short-lived, audience-scoped statement a *paired
|
|
6
|
+
* device* makes about itself — "this device, paired to this product against
|
|
7
|
+
* this server, wants to talk to `<audience>` for the next two minutes" — signed
|
|
8
|
+
* with the same Ed25519 device identity key `attestation.ts`'s device proof
|
|
9
|
+
* uses. A sibling CLI installed alongside the daemon presents one to the host's
|
|
10
|
+
* cloud, which exchanges it for a product session. It is NOT a request-bound
|
|
11
|
+
* proof (`attestation.ts`) and the two must never be interchangeable; see the
|
|
12
|
+
* domain prefix below.
|
|
13
|
+
*
|
|
14
|
+
* Four decisions this file encodes, none of them re-litigable here:
|
|
15
|
+
*
|
|
16
|
+
* 1. **A custom JSON signing envelope, not JWS.** The domain prefix has to be
|
|
17
|
+
* *inside* the signed bytes. JWS puts its type tag in a header that no
|
|
18
|
+
* verifier is required to check, which is a fail-open shape: a token minted
|
|
19
|
+
* for one purpose verifies for another as long as the key matches. So this
|
|
20
|
+
* clones the mechanism `attestation.ts` already froze — RFC 8785-subset
|
|
21
|
+
* canonicalization (`canonicalizeJson`, imported, never re-implemented) plus
|
|
22
|
+
* a golden fixture pinning the exact bytes.
|
|
23
|
+
* 2. **What the claims deliberately do NOT carry.** No `devicePublicKey`: a
|
|
24
|
+
* verifier must resolve the key from its own device directory by `deviceId`,
|
|
25
|
+
* or the envelope becomes self-authenticating. No caller identity: every
|
|
26
|
+
* process under the same UID can reach the control socket, so a "who asked"
|
|
27
|
+
* field would be synthesized authority, not evidence. No `keyId`: there is
|
|
28
|
+
* no key-rotation story for this envelope yet, and a field nothing populates
|
|
29
|
+
* honestly is a structure that invites a verifier to trust it.
|
|
30
|
+
* 3. **`audience` is a single string, never an array.** A multi-audience token
|
|
31
|
+
* forces every verifier to agree on the same containment rule; one string
|
|
32
|
+
* compared with `===` cannot be got wrong.
|
|
33
|
+
* 4. **The verifier cannot forget the revocation check.** {@link
|
|
34
|
+
* verifyDeviceAssertion} takes `revoked` as a REQUIRED dependency, so a
|
|
35
|
+
* caller that never looked the device row up does not compile. The daemon's
|
|
36
|
+
* own local checks (see `@byok-sdk/client`'s `assertion.issue`) are only half
|
|
37
|
+
* of revocation; the other half is this recheck at exchange time, and no
|
|
38
|
+
* documentation may claim the daemon satisfies "synchronous invalidation"
|
|
39
|
+
* on its own.
|
|
40
|
+
*
|
|
41
|
+
* Like `attestation.ts`, this module is crypto-free: signature verification is
|
|
42
|
+
* an injected port (`DeviceAssertionVerifier`), because core must load on
|
|
43
|
+
* Workers and `node:crypto`/WebCrypto disagree about key handling.
|
|
44
|
+
*/
|
|
45
|
+
import { z } from 'zod';
|
|
46
|
+
import { type JsonObject } from './attestation';
|
|
47
|
+
/** Envelope schema id, self-consistent with the domain prefix below. */
|
|
48
|
+
export declare const DEVICE_ASSERTION_SCHEMA_ID = "byok-device-assertion-v1";
|
|
49
|
+
/**
|
|
50
|
+
* Domain separation prefix, prepended to the canonical claim bytes before
|
|
51
|
+
* signing.
|
|
52
|
+
*
|
|
53
|
+
* Must remain mutually NON-PREFIX with the other two things this same Ed25519
|
|
54
|
+
* device key signs — `byok-nonce-v1\n` (challenge/token renewal, see
|
|
55
|
+
* `@byok-sdk/client`'s `device-keys.ts`) and `byok-device-proof-v1\n`
|
|
56
|
+
* (`attestation.ts`) — so no signature over one domain can ever be reinterpreted
|
|
57
|
+
* as a signature over another. `packages/core/src/__tests__/device-assertion.test.ts`
|
|
58
|
+
* asserts the three-way non-prefix property directly; that assertion is the
|
|
59
|
+
* falsifier for this whole design, not a nicety.
|
|
60
|
+
*/
|
|
61
|
+
export declare const DEVICE_ASSERTION_DOMAIN_PREFIX = "byok-device-assertion-v1\n";
|
|
62
|
+
export declare const DEVICE_ASSERTION_VERSION = 1;
|
|
63
|
+
/** Signature algorithms this envelope version admits. */
|
|
64
|
+
export declare const DEVICE_ASSERTION_ALGORITHMS: readonly ['ed25519'];
|
|
65
|
+
export type DeviceAssertionAlgorithm = (typeof DEVICE_ASSERTION_ALGORITHMS)[number];
|
|
66
|
+
/**
|
|
67
|
+
* Default assertion lifetime. Short on purpose: the daemon keeps no `jti`
|
|
68
|
+
* ledger (it is not on the verification path and could not stop a real replay
|
|
69
|
+
* anyway), so a narrow expiry window plus a burn-on-use verifier is the whole
|
|
70
|
+
* replay story.
|
|
71
|
+
*/
|
|
72
|
+
export declare const DEVICE_ASSERTION_DEFAULT_TTL_MS = 120000;
|
|
73
|
+
/**
|
|
74
|
+
* Hard ceiling on the lifetime, enforced at BOTH ends: a daemon refuses to be
|
|
75
|
+
* configured above it, and {@link verifyDeviceAssertion} refuses an envelope
|
|
76
|
+
* whose own `issuedAt`→`expiresAt` span exceeds it regardless of who minted it.
|
|
77
|
+
*/
|
|
78
|
+
export declare const DEVICE_ASSERTION_MAX_TTL_MS = 300000;
|
|
79
|
+
/** Bound on the `audience` claim, in UTF-8 bytes — an allowlist entry is a short identifier, not a document. */
|
|
80
|
+
export declare const DEVICE_ASSERTION_AUDIENCE_MAX_BYTES = 256;
|
|
81
|
+
/**
|
|
82
|
+
* The signed claim set. `strictObject` with every member REQUIRED: an optional
|
|
83
|
+
* claim is a claim a verifier may or may not see, and this envelope is small
|
|
84
|
+
* enough that there is no honest reason for one.
|
|
85
|
+
*
|
|
86
|
+
* `issuer` is the paired server's origin (scheme + host + port, normalized) —
|
|
87
|
+
* it binds the assertion to the deployment the device is actually paired
|
|
88
|
+
* against, so an assertion minted by a device paired to a staging server cannot
|
|
89
|
+
* be presented to production.
|
|
90
|
+
*/
|
|
91
|
+
export declare const DeviceAssertionClaimsSchema: z.ZodObject<{
|
|
92
|
+
version: z.ZodLiteral<1>;
|
|
93
|
+
issuer: z.ZodString;
|
|
94
|
+
productId: z.ZodString;
|
|
95
|
+
deviceId: z.ZodString;
|
|
96
|
+
audience: z.ZodString;
|
|
97
|
+
jti: z.ZodString;
|
|
98
|
+
issuedAt: z.ZodISODateTime;
|
|
99
|
+
expiresAt: z.ZodISODateTime;
|
|
100
|
+
}, z.core.$strict>;
|
|
101
|
+
export type DeviceAssertionClaims = z.infer<typeof DeviceAssertionClaimsSchema>;
|
|
102
|
+
export declare const DeviceAssertionEnvelopeV1Schema: z.ZodObject<{
|
|
103
|
+
schema: z.ZodLiteral<"byok-device-assertion-v1">;
|
|
104
|
+
algorithm: z.ZodEnum<{
|
|
105
|
+
ed25519: "ed25519";
|
|
106
|
+
}>;
|
|
107
|
+
protected: z.ZodObject<{
|
|
108
|
+
version: z.ZodLiteral<1>;
|
|
109
|
+
issuer: z.ZodString;
|
|
110
|
+
productId: z.ZodString;
|
|
111
|
+
deviceId: z.ZodString;
|
|
112
|
+
audience: z.ZodString;
|
|
113
|
+
jti: z.ZodString;
|
|
114
|
+
issuedAt: z.ZodISODateTime;
|
|
115
|
+
expiresAt: z.ZodISODateTime;
|
|
116
|
+
}, z.core.$strict>;
|
|
117
|
+
signature: z.ZodString;
|
|
118
|
+
}, z.core.$strict>;
|
|
119
|
+
export type DeviceAssertionEnvelopeV1 = z.infer<typeof DeviceAssertionEnvelopeV1Schema>;
|
|
120
|
+
/**
|
|
121
|
+
* Parses an envelope fail-closed.
|
|
122
|
+
*
|
|
123
|
+
* @throws {ByokCoreError} code `assertion_envelope_invalid`.
|
|
124
|
+
*/
|
|
125
|
+
export declare function parseDeviceAssertionEnvelope(input: unknown): DeviceAssertionEnvelopeV1;
|
|
126
|
+
/**
|
|
127
|
+
* Projects claims into the exact JSON object that gets canonicalized.
|
|
128
|
+
*
|
|
129
|
+
* Built field by field rather than by spreading the parsed object — the same
|
|
130
|
+
* discipline `deviceProofCanonicalClaims` documents. Nothing here is optional,
|
|
131
|
+
* so there is no absent-key decision to get wrong; the explicit projection is
|
|
132
|
+
* what keeps it that way if a field is ever added.
|
|
133
|
+
*/
|
|
134
|
+
export declare function deviceAssertionCanonicalClaims(claims: DeviceAssertionClaims): JsonObject;
|
|
135
|
+
/** Canonical JSON text of the claim set, without the domain prefix. */
|
|
136
|
+
export declare function deviceAssertionCanonicalJson(claims: DeviceAssertionClaims): string;
|
|
137
|
+
/**
|
|
138
|
+
* The exact bytes a device signs and a verifier reconstructs:
|
|
139
|
+
* `byok-device-assertion-v1\n` followed by the canonical claim JSON, UTF-8
|
|
140
|
+
* encoded.
|
|
141
|
+
*
|
|
142
|
+
* Frozen by `src/__tests__/golden/device-assertion-v1.canonical.json`.
|
|
143
|
+
*/
|
|
144
|
+
export declare function deviceAssertionSigningInput(claims: DeviceAssertionClaims): Uint8Array;
|
|
145
|
+
export interface DeviceAssertionVerifyInput {
|
|
146
|
+
readonly algorithm: DeviceAssertionAlgorithm;
|
|
147
|
+
/** Raw public key, base64url — the JWK `x` encoding the device registry stores. */
|
|
148
|
+
readonly publicKey: string;
|
|
149
|
+
readonly signature: string;
|
|
150
|
+
readonly signingInput: Uint8Array;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Injected signature verification, for the same reason `DeviceProofVerifier`
|
|
154
|
+
* exists: core is Node-free and Workers-safe, so it answers no cryptographic
|
|
155
|
+
* question itself. Kept separate from `DeviceProofVerifier` even though the
|
|
156
|
+
* shapes coincide — one composition object satisfies both — because this file's
|
|
157
|
+
* entire purpose is that the two domains never become interchangeable, and a
|
|
158
|
+
* shared type is the first step toward a shared code path.
|
|
159
|
+
*/
|
|
160
|
+
export interface DeviceAssertionVerifier {
|
|
161
|
+
verify(input: DeviceAssertionVerifyInput): Promise<boolean>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* The device-row fields a verification reads — the verifier's OWN directory
|
|
165
|
+
* row, resolved by `deviceId`, never anything the envelope carried.
|
|
166
|
+
*
|
|
167
|
+
* Both fields together, from one lookup, are what make forgetting impossible:
|
|
168
|
+
* the caller cannot obtain `publicKeyJwkX` without also obtaining the current
|
|
169
|
+
* `revoked` state, because they arrive as one object from one call.
|
|
170
|
+
*/
|
|
171
|
+
export interface DeviceAssertionDeviceRow {
|
|
172
|
+
/** JWK `x` of the device's registered Ed25519 public key. The ONLY key a signature is ever checked against. */
|
|
173
|
+
readonly publicKeyJwkX: string;
|
|
174
|
+
/** The row's CURRENT revocation state, read in the same lookup as the key. */
|
|
175
|
+
readonly revoked: boolean;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Everything a verification needs that is NOT in the envelope.
|
|
179
|
+
*
|
|
180
|
+
* The device row is supplied through a LOOKUP PORT, not as a pre-fetched
|
|
181
|
+
* value, and that is the whole point (this is the faithful clone of
|
|
182
|
+
* `DeviceProofVerifier`'s "core is never a second authority on device
|
|
183
|
+
* identity" shape). `verifyDeviceAssertion` reads `deviceId` from the parsed
|
|
184
|
+
* claims and calls `lookupDevice(deviceId)` ITSELF, so:
|
|
185
|
+
*
|
|
186
|
+
* - There is no way to invoke a verification without providing the means to
|
|
187
|
+
* look the current row up — "I forgot to check revocation" cannot be
|
|
188
|
+
* expressed, because the function does the lookup, not the caller.
|
|
189
|
+
* - Both the public key AND the revocation state come from that one row, so a
|
|
190
|
+
* caller cannot pass a key while claiming `revoked: false` from thin air.
|
|
191
|
+
* - The `deviceId` handed to `lookupDevice` is the claimed one; the row it
|
|
192
|
+
* returns is authority. A device asserting an identity it is not is caught
|
|
193
|
+
* by the lookup missing, or by the returned row's key failing the signature.
|
|
194
|
+
*/
|
|
195
|
+
export interface DeviceAssertionVerifyDeps {
|
|
196
|
+
readonly verifier: DeviceAssertionVerifier;
|
|
197
|
+
/**
|
|
198
|
+
* Resolve the verifier's own device row by the claimed `deviceId`.
|
|
199
|
+
* `undefined` for an unknown device. Sync or async; awaited either way.
|
|
200
|
+
*/
|
|
201
|
+
readonly lookupDevice: (deviceId: string) => Promise<DeviceAssertionDeviceRow | undefined> | DeviceAssertionDeviceRow | undefined;
|
|
202
|
+
/** Injected instant — core never reads a wall clock (`stores.ts`'s `Clock`). */
|
|
203
|
+
readonly now: Date;
|
|
204
|
+
/** Bound on `issuedAt`→`expiresAt`. Defaults to (and may never exceed) {@link DEVICE_ASSERTION_MAX_TTL_MS}. */
|
|
205
|
+
readonly maxLifetimeMs?: number;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Verifies an assertion and returns its claims, or `undefined`.
|
|
209
|
+
*
|
|
210
|
+
* Every rejected state collapses to `undefined` — malformed input, an unknown
|
|
211
|
+
* or revoked device, an expired or over-long window, a bad signature — so a
|
|
212
|
+
* route has one response for all of them and cannot accidentally leak which
|
|
213
|
+
* check failed. That is the same shape `authenticateDeviceProof`
|
|
214
|
+
* (`@byok-sdk/cloud`) already uses.
|
|
215
|
+
*
|
|
216
|
+
* The row lookup and both authority reads (key, revocation) happen INSIDE this
|
|
217
|
+
* function — see {@link DeviceAssertionVerifyDeps}. What the caller MUST still
|
|
218
|
+
* do afterward, and this cannot: assert `claims.audience` equals the audience
|
|
219
|
+
* it actually serves, assert `claims.issuer`/`claims.productId` match its own
|
|
220
|
+
* deployment, and BURN `claims.jti` so the assertion cannot be presented
|
|
221
|
+
* twice. The daemon keeps no `jti` ledger; single use is entirely the
|
|
222
|
+
* verifier's job.
|
|
223
|
+
*/
|
|
224
|
+
export declare function verifyDeviceAssertion(input: unknown, deps: DeviceAssertionVerifyDeps): Promise<DeviceAssertionClaims | undefined>;
|
package/dist/errors.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare const CORE_ERROR_CODES: {
|
|
|
36
36
|
readonly capability_unavailable: 'capability_unavailable';
|
|
37
37
|
readonly proof_envelope_invalid: 'proof_envelope_invalid';
|
|
38
38
|
readonly proof_canonicalization_failed: 'proof_canonicalization_failed';
|
|
39
|
+
readonly assertion_envelope_invalid: 'assertion_envelope_invalid';
|
|
39
40
|
readonly mailbox_message_not_found: 'mailbox_message_not_found';
|
|
40
41
|
readonly mailbox_cursor_regression: 'mailbox_cursor_regression';
|
|
41
42
|
readonly board_item_not_found: 'board_item_not_found';
|
|
@@ -51,6 +52,7 @@ export declare const CORE_ERROR_CODES: {
|
|
|
51
52
|
readonly activity_batch_invalid: 'activity_batch_invalid';
|
|
52
53
|
readonly hint_ttl_invalid: 'hint_ttl_invalid';
|
|
53
54
|
readonly hint_rate_limited: 'hint_rate_limited';
|
|
55
|
+
readonly object_key_prefix_invalid: 'object_key_prefix_invalid';
|
|
54
56
|
readonly object_not_found: 'object_not_found';
|
|
55
57
|
readonly object_state_invalid: 'object_state_invalid';
|
|
56
58
|
readonly storage_entitlement_missing: 'storage_entitlement_missing';
|
|
@@ -61,6 +63,8 @@ export declare const CORE_ERROR_CODES: {
|
|
|
61
63
|
readonly storage_reservation_expired: 'storage_reservation_expired';
|
|
62
64
|
readonly storage_integrity_mismatch: 'storage_integrity_mismatch';
|
|
63
65
|
readonly storage_write_suspended: 'storage_write_suspended';
|
|
66
|
+
readonly skill_pack_manifest_invalid: 'skill_pack_manifest_invalid';
|
|
67
|
+
readonly skill_pack_frontmatter_invalid: 'skill_pack_frontmatter_invalid';
|
|
64
68
|
};
|
|
65
69
|
export type CoreErrorCode = (typeof CORE_ERROR_CODES)[keyof typeof CORE_ERROR_CODES];
|
|
66
70
|
/** Base error for every failure this package raises. */
|
|
@@ -6,6 +6,7 @@ export { InMemoryTruthStore } from './truth';
|
|
|
6
6
|
export { InMemoryPresenceStore, InMemoryActivityStore } from './presence';
|
|
7
7
|
export { InMemoryObjectStore } from './blob';
|
|
8
8
|
export { InMemoryQuotaStore } from './quota';
|
|
9
|
+
export { InMemorySkillPackStore } from './skill-pack';
|
|
9
10
|
export interface InMemoryCoreOptions {
|
|
10
11
|
/** Defaults to a fresh {@link createMutableClock}, so TTL behavior is deterministic. */
|
|
11
12
|
readonly clock?: Clock;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory {@link SkillPackStore} reference (plan `skill-pack-delivery-channel`).
|
|
3
|
+
*
|
|
4
|
+
* The interesting property is what `publish` refuses. This store cannot hash —
|
|
5
|
+
* core has no crypto — so it is NOT the integrity authority for a pack, and it
|
|
6
|
+
* does not pretend to be: the publisher mints the addresses and the installing
|
|
7
|
+
* device re-derives and verifies every one of them. What this store CAN check
|
|
8
|
+
* without crypto, it checks, and rejects rather than storing a pack whose
|
|
9
|
+
* manifest and bytes already disagree at publish time: the declared path set
|
|
10
|
+
* must be exactly the delivered path set, and every delivered file's UTF-8 byte
|
|
11
|
+
* length must equal what its row declared.
|
|
12
|
+
*
|
|
13
|
+
* Storing that pair unchecked would be the worse failure mode by far — the
|
|
14
|
+
* device would fetch, verify, reject, and have no way to tell a corrupt
|
|
15
|
+
* publication from a tampered response.
|
|
16
|
+
*/
|
|
17
|
+
import { type SkillPackFileContent, type SkillPackListQuery, type SkillPackManifest, type SkillPackPublishInput, type SkillPackStore } from '../skill-pack';
|
|
18
|
+
import { type TenantId } from '../tenant';
|
|
19
|
+
export declare class InMemorySkillPackStore implements SkillPackStore {
|
|
20
|
+
#private;
|
|
21
|
+
publish(tenant: TenantId, input: SkillPackPublishInput): Promise<SkillPackManifest>;
|
|
22
|
+
get(tenant: TenantId, name: string): Promise<SkillPackManifest | undefined>;
|
|
23
|
+
list(tenant: TenantId, query: SkillPackListQuery): Promise<readonly SkillPackManifest[]>;
|
|
24
|
+
readFile(tenant: TenantId, name: string, path: string): Promise<SkillPackFileContent | undefined>;
|
|
25
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,23 +18,28 @@ export { ByokCoreError, CoreConflictError, CORE_ERROR_CODES, isCoreError, isCore
|
|
|
18
18
|
export type { CoreErrorCode } from './errors';
|
|
19
19
|
export { CANONICAL_TIMESTAMP_PATTERN, assertCanonicalTimestamp, isCanonicalTimestamp, } from './time';
|
|
20
20
|
export { MAILBOX_MESSAGE_STATES } from './mailbox';
|
|
21
|
-
export type { MailboxAdvanceCursorInput, MailboxAppendInput, MailboxCursorState, MailboxMessage, MailboxMessageState, MailboxPage, MailboxReadQuery, MailboxRetentionInput, MailboxRetentionResult, MailboxStore, } from './mailbox';
|
|
21
|
+
export type { MailboxAdvanceCursorInput, MailboxAppendInput, MailboxBody, MailboxCursorState, MailboxMessage, MailboxMessageState, MailboxPage, MailboxReadQuery, MailboxRetentionInput, MailboxRetentionResult, MailboxStore, } from './mailbox';
|
|
22
22
|
export { BOARD_STATUSES, BOARD_TRANSITIONS, isLegalBoardTransition } from './board';
|
|
23
23
|
export type { BoardAssignee, BoardClaimInput, BoardItem, BoardItemInput, BoardListQuery, BoardPage, BoardStatus, BoardStatusUpdateInput, BoardStore, BoardUnclaimInput, } from './board';
|
|
24
24
|
export { TRUTH_RECORD_KINDS } from './truth';
|
|
25
25
|
export type { SnapshotWriteInput, TerminalWriteInput, TruthBodyRef, TruthManifestEntry, TruthManifestQuery, TruthRecord, TruthRecordKind, TruthRecordSelector, TruthStore, } from './truth';
|
|
26
26
|
export { PRESENCE_LEVELS, DEFAULT_ACTIVITY_CAPACITY } from './presence';
|
|
27
27
|
export type { ActivityAppendInput, ActivityEntry, ActivityStore, ActivityTail, PresenceHint, PresenceHintInput, PresenceLevel, PresenceStore, } from './presence';
|
|
28
|
-
export { CONTENT_HASH_PATTERN, OBJECT_STATES, OBJECT_STATE_TRANSITIONS, contentHash, isContentHash, isLegalObjectTransition, tenantObjectKey, } from './blob';
|
|
29
|
-
export type { ContentHash, ObjectCommitInput, ObjectListQuery, ObjectManifestEntry, ObjectManifestInput, ObjectReference, ObjectReferenceInput, ObjectState, ObjectStore, } from './blob';
|
|
28
|
+
export { CONTENT_HASH_PATTERN, OBJECT_KEY_PREFIX_PATTERN, OBJECT_STATES, OBJECT_STATE_TRANSITIONS, contentHash, isContentHash, isLegalObjectTransition, objectKeyPrefix, tenantObjectKey, } from './blob';
|
|
29
|
+
export type { ContentHash, ObjectCommitInput, ObjectKeyPrefix, ObjectListQuery, ObjectManifestEntry, ObjectManifestInput, ObjectReference, ObjectReferenceInput, ObjectState, ObjectStore, } from './blob';
|
|
30
30
|
export { STORAGE_ERROR_CODES, STORAGE_ERROR_HTTP_STATUS, STORAGE_RESERVATION_STATES, STORAGE_WRITE_KINDS, STORAGE_WRITE_POSTURES, } from './quota';
|
|
31
31
|
export type { MailboxUsageDeltaInput, QuotaStore, StorageErrorCode, StorageFinalizeInput, StorageFinalizeResult, StorageReservation, StorageReservationInput, StorageReservationState, StorageStatus, StorageWriteKind, StorageWritePosture, TenantStorageEntitlement, TenantStorageEntitlementInput, TenantStorageUsage, } from './quota';
|
|
32
32
|
export { CAPABILITY_DECLARATION_SCHEMA_ID, CAPABILITY_NAME_PATTERN, CapabilityDeclarationSchema, assertCapability, hasCapability, parseCapabilityDeclaration, } from './capabilities';
|
|
33
33
|
export type { CapabilityDeclaration } from './capabilities';
|
|
34
|
+
export { SKILL_FRONTMATTER_FIELDS, SKILL_PACK_DESCRIPTION_MAX_LENGTH, SKILL_PACK_ENTRY_PATH, SKILL_PACK_FILE_MAX_BYTES, SKILL_PACK_FILE_PATH_MAX_LENGTH, SKILL_PACK_FILE_PATH_PATTERN, SKILL_PACK_FORBIDDEN_FIELDS, SKILL_PACK_MANIFEST_SCHEMA_ID, SKILL_PACK_MAX_BYTES, SKILL_PACK_MAX_FILES, SKILL_PACK_NAME_MAX_LENGTH, SKILL_PACK_NAME_PATTERN, SKILL_PACK_REJECTIONS, SKILL_PACK_VERSION_PATTERN, SkillPackFileSchema, SkillPackManifestSchema, checkSkillPackEntry, checkSkillPackFileContent, checkSkillPackManifest, isSkillPackPathSafe, parseSkillFrontmatter, parseSkillPackManifest, skillPackContentHashInput, } from './skill-pack';
|
|
35
|
+
export type { ObservedSkillPackFile, SkillFrontmatter, SkillPackCheck, SkillPackFile, SkillPackFileContent, SkillPackListQuery, SkillPackManifest, SkillPackPublishInput, SkillPackRejection, SkillPackStore, } from './skill-pack';
|
|
34
36
|
export { CORE_STORE_NAMES } from './stores';
|
|
35
37
|
export type { Clock, CoreStoreName, CoreStores, MutableClock } from './stores';
|
|
36
|
-
export { CORE_PORT_INTERFACES, CORE_PORT_METHODS } from './ports-contract';
|
|
37
|
-
export { DEVICE_PROOF_ALGORITHMS, DEVICE_PROOF_DOMAIN_PREFIX, DEVICE_PROOF_SCHEMA_ID, DEVICE_PROOF_VERSION, DeviceProofEnvelopeV1Schema, DeviceProofProtectedClaimsSchema, canonicalizeJson, canonicalizeJsonBytes, deviceProofCanonicalClaims, deviceProofCanonicalJson, deviceProofSigningInput, parseDeviceProofEnvelope, } from './attestation';
|
|
38
|
+
export { CORE_NON_COMPOSITION_PORT_NAMES, CORE_PORT_INTERFACES, CORE_PORT_METHODS, } from './ports-contract';
|
|
39
|
+
export { DEVICE_PROOF_ALGORITHMS, DEVICE_PROOF_DOMAIN_PREFIX, DEVICE_PROOF_HEADER, DEVICE_PROOF_SCHEMA_ID, DEVICE_PROOF_VERSION, DeviceProofEnvelopeV1Schema, DeviceProofProtectedClaimsSchema, canonicalizeJson, canonicalizeJsonBytes, deviceProofCanonicalClaims, deviceProofCanonicalJson, deviceProofSigningInput, parseDeviceProofEnvelope, } from './attestation';
|
|
38
40
|
export type { DeviceProofAlgorithm, DeviceProofEnvelopeV1, DeviceProofProtectedClaims, DeviceProofVerifier, DeviceProofVerifyInput, JsonObject, JsonPrimitive, JsonValue, } from './attestation';
|
|
39
|
-
export {
|
|
41
|
+
export { DEVICE_ASSERTION_ALGORITHMS, DEVICE_ASSERTION_AUDIENCE_MAX_BYTES, DEVICE_ASSERTION_DEFAULT_TTL_MS, DEVICE_ASSERTION_DOMAIN_PREFIX, DEVICE_ASSERTION_MAX_TTL_MS, DEVICE_ASSERTION_SCHEMA_ID, DEVICE_ASSERTION_VERSION, DeviceAssertionClaimsSchema, DeviceAssertionEnvelopeV1Schema, deviceAssertionCanonicalClaims, deviceAssertionCanonicalJson, deviceAssertionSigningInput, parseDeviceAssertionEnvelope, verifyDeviceAssertion, } from './device-assertion';
|
|
42
|
+
export type { DeviceAssertionAlgorithm, DeviceAssertionClaims, DeviceAssertionDeviceRow, DeviceAssertionEnvelopeV1, DeviceAssertionVerifier, DeviceAssertionVerifyDeps, DeviceAssertionVerifyInput, } from './device-assertion';
|
|
43
|
+
export { NONCE_SIGNING_DOMAIN, nonceSigningBytes } from './pairing';
|
|
44
|
+
export { IN_MEMORY_CLOCK_EPOCH, InMemoryActivityStore, InMemoryBoardStore, InMemoryMailboxStore, InMemoryObjectStore, InMemoryPresenceStore, InMemoryQuotaStore, InMemorySkillPackStore, InMemoryTruthStore, createInMemoryCoreStores, createInMemoryCoreCompositionWithClock, createMutableClock, } from './in-memory/index';
|
|
40
45
|
export type { InMemoryCoreComposition, InMemoryCoreOptions } from './in-memory/index';
|