@byok-sdk/core 0.2.0 → 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.
@@ -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-postgres` 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 { IN_MEMORY_CLOCK_EPOCH, InMemoryActivityStore, InMemoryBoardStore, InMemoryMailboxStore, InMemoryObjectStore, InMemoryPresenceStore, InMemoryQuotaStore, InMemoryTruthStore, createInMemoryCoreStores, createInMemoryCoreCompositionWithClock, createMutableClock, } from './in-memory/index';
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';