@byollm/protocol 0.1.0-alpha.30 → 0.1.0-alpha.32
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/README.md +2 -2
- package/dist/index.d.ts +116 -1
- package/dist/index.js +201 -89
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
> [!WARNING]
|
|
2
|
-
> **Alpha (`0.1.0-alpha.
|
|
2
|
+
> **Alpha (`0.1.0-alpha.32`) — under active development. Don't use this yet.**
|
|
3
3
|
>
|
|
4
4
|
> Install it deliberately: `npm install @byollm/protocol@alpha`.
|
|
5
5
|
>
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
> packages published and `@byollm/server` did not: a Sigstore
|
|
84
84
|
> transparency-log 409 on its provenance attestation. The workflow's
|
|
85
85
|
> "already published" guard correctly refuses to resume a partial publish,
|
|
86
|
-
> so `0.1.0-alpha.
|
|
86
|
+
> so `0.1.0-alpha.32` is that release, whole.
|
|
87
87
|
>
|
|
88
88
|
> If you run the Supabase adapter, `alpha.21` needs
|
|
89
89
|
> `20260819010000_completed_by_lease_id.sql`: alpha.19 shipped §3.6's
|
package/dist/index.d.ts
CHANGED
|
@@ -1108,6 +1108,110 @@ declare function verifyRequest(input: {
|
|
|
1108
1108
|
maxSkewMs?: number;
|
|
1109
1109
|
}): SignatureFailure | null;
|
|
1110
1110
|
|
|
1111
|
+
/**
|
|
1112
|
+
* Rotation — byollm_009 Amendment C.
|
|
1113
|
+
*
|
|
1114
|
+
* A site holding identity key **K1** wants to be known by **K2**. It publishes
|
|
1115
|
+
* a *succession*: K2, plus a signature by K1 over a statement naming both key
|
|
1116
|
+
* ids. That signature is the entire mechanism, and the reason rotation can be
|
|
1117
|
+
* automatic without becoming a hole is that **the relay cannot mint one** — it
|
|
1118
|
+
* never holds K1. It is the same trust step a daemon already performs at
|
|
1119
|
+
* pairing, applied to the site's own succession.
|
|
1120
|
+
*
|
|
1121
|
+
* ## Why the statement names both keys
|
|
1122
|
+
*
|
|
1123
|
+
* A signature over K2 alone could be lifted from this site's record and
|
|
1124
|
+
* replayed into another site's, moving *that* site to K2 — a key the attacker
|
|
1125
|
+
* holds. Naming the predecessor binds the succession to one chain, and it is
|
|
1126
|
+
* the reason `verifyLink` takes the id it expects to be succeeding from
|
|
1127
|
+
* rather than reading it out of the statement it is checking.
|
|
1128
|
+
*/
|
|
1129
|
+
/** The domain separator. Distinct from every other thing an identity signs. */
|
|
1130
|
+
declare const SUCCESSION_CONTEXT = "byollm/v1/site-succession";
|
|
1131
|
+
/**
|
|
1132
|
+
* How long a retired key may still sign work — Amendment C, ruling 2.
|
|
1133
|
+
*
|
|
1134
|
+
* A protocol constant and not the site's to choose. Per-site overlap
|
|
1135
|
+
* arithmetic is exactly the kind of number that has to mean one thing
|
|
1136
|
+
* everywhere, and a site that could choose it could choose *forever*, which is
|
|
1137
|
+
* a two-key site permanently and a second key nobody ever notices retiring.
|
|
1138
|
+
*
|
|
1139
|
+
* Seven days: long enough that a daemon which polls daily and a laptop shut
|
|
1140
|
+
* for a long weekend both see the new record before the old key stops working,
|
|
1141
|
+
* short enough that "which key is live" is never an interesting question.
|
|
1142
|
+
*/
|
|
1143
|
+
declare const RETIREMENT_WINDOW_MS: number;
|
|
1144
|
+
/**
|
|
1145
|
+
* The longest chain a daemon will walk — Amendment C, ruling 1.
|
|
1146
|
+
*
|
|
1147
|
+
* **A denial-of-service guard, not policy.** The bound exists so a projection
|
|
1148
|
+
* cannot make a daemon verify ten thousand signatures, not to express an
|
|
1149
|
+
* opinion about how often a site may rotate. A site that legitimately exceeds
|
|
1150
|
+
* it has a re-pair ahead of it, which is why it is generous: at one rotation a
|
|
1151
|
+
* quarter this is sixteen years.
|
|
1152
|
+
*/
|
|
1153
|
+
declare const MAX_SUCCESSION_CHAIN = 64;
|
|
1154
|
+
/** One step of a chain: a key, and the signature by it over its successor. */
|
|
1155
|
+
declare const Succession: z.ZodObject<{
|
|
1156
|
+
identity: z.ZodObject<{
|
|
1157
|
+
identity: z.ZodString;
|
|
1158
|
+
encryption: z.ZodString;
|
|
1159
|
+
encryptionSig: z.ZodString;
|
|
1160
|
+
}, z.core.$strict>;
|
|
1161
|
+
signature: z.ZodString;
|
|
1162
|
+
}, z.core.$strict>;
|
|
1163
|
+
type Succession = z.infer<typeof Succession>;
|
|
1164
|
+
/** The exact bytes signed. One definition; both sides call it. */
|
|
1165
|
+
declare function successionStatement(fromKeyId: string, toKeyId: string): Uint8Array;
|
|
1166
|
+
/**
|
|
1167
|
+
* Sign a succession from the keys being retired to the identity taking over.
|
|
1168
|
+
*
|
|
1169
|
+
* Takes `StoredKeys` for the predecessor because only the holder of K1's
|
|
1170
|
+
* private half can produce this, which is the property the whole design rests
|
|
1171
|
+
* on. A site calls this once, at rotation, on the machine holding its keys.
|
|
1172
|
+
*/
|
|
1173
|
+
declare function signSuccession(previous: StoredKeys, next: PublicIdentity): Succession;
|
|
1174
|
+
/**
|
|
1175
|
+
* Check one link: did `link.identity` sign over succeeding to `toKeyId`?
|
|
1176
|
+
*
|
|
1177
|
+
* `toKeyId` is passed in rather than read from anywhere in `link`, and that is
|
|
1178
|
+
* the load-bearing detail. A verifier that recovered the successor from the
|
|
1179
|
+
* signed statement would accept a statement about *any* successor, which is
|
|
1180
|
+
* the replay this design names in C.1 — the signature is genuine, the
|
|
1181
|
+
* successor it names is not the one being installed.
|
|
1182
|
+
*/
|
|
1183
|
+
declare function verifyLink(link: Succession, toKeyId: string): boolean;
|
|
1184
|
+
/** Why a chain was refused, in the words a log line uses. */
|
|
1185
|
+
type SuccessionFailure = "no-chain" | "too-long" | "unknown-origin" | "broken-link";
|
|
1186
|
+
interface SuccessionWalk {
|
|
1187
|
+
/** The ids the chain passes through, oldest first, ending at the current. */
|
|
1188
|
+
readonly path: string[];
|
|
1189
|
+
/** The approved id the chain reached, when it reached one. */
|
|
1190
|
+
readonly from?: string;
|
|
1191
|
+
readonly failure?: SuccessionFailure;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Walk a chain from the key being presented back to a key already approved.
|
|
1195
|
+
*
|
|
1196
|
+
* `chain` is ordered oldest last, as the projection carries it — so walking it
|
|
1197
|
+
* means starting at the current key and stepping backwards, each link proving
|
|
1198
|
+
* that its holder signed for the id in front of it.
|
|
1199
|
+
*
|
|
1200
|
+
* Returns the approved id it reached, or why it did not. **Deliberately
|
|
1201
|
+
* returns rather than throws**: a chain that does not verify is ordinary
|
|
1202
|
+
* hostile input, and the caller's job is to keep its existing pin and say so.
|
|
1203
|
+
*
|
|
1204
|
+
* `approved` is asked as a predicate rather than taken as a set because the
|
|
1205
|
+
* daemon's notion of "already approved" includes tombstoned ids — a site that
|
|
1206
|
+
* left the allowlist and came back is still a site this machine has vouched
|
|
1207
|
+
* for, and rotation must not become a way to launder that distinction away.
|
|
1208
|
+
*/
|
|
1209
|
+
declare function walkSuccession(input: {
|
|
1210
|
+
current: string;
|
|
1211
|
+
chain: readonly Succession[];
|
|
1212
|
+
approved: (keyId: string) => boolean;
|
|
1213
|
+
}): SuccessionWalk;
|
|
1214
|
+
|
|
1111
1215
|
/**
|
|
1112
1216
|
* The normative MUSTs of protocol v0, as data.
|
|
1113
1217
|
*
|
|
@@ -1696,6 +1800,17 @@ declare const HeartbeatResponse: z.ZodObject<{
|
|
|
1696
1800
|
encryption: z.ZodString;
|
|
1697
1801
|
encryptionSig: z.ZodString;
|
|
1698
1802
|
}, z.core.$strict>>;
|
|
1803
|
+
successions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1804
|
+
succeeds: z.ZodArray<z.ZodObject<{
|
|
1805
|
+
identity: z.ZodObject<{
|
|
1806
|
+
identity: z.ZodString;
|
|
1807
|
+
encryption: z.ZodString;
|
|
1808
|
+
encryptionSig: z.ZodString;
|
|
1809
|
+
}, z.core.$strict>;
|
|
1810
|
+
signature: z.ZodString;
|
|
1811
|
+
}, z.core.$strict>>;
|
|
1812
|
+
retiringUntil: z.ZodOptional<z.ZodNumber>;
|
|
1813
|
+
}, z.core.$strict>>>;
|
|
1699
1814
|
cancel: z.ZodArray<z.ZodObject<{
|
|
1700
1815
|
jobId: z.ZodString;
|
|
1701
1816
|
leaseId: z.ZodString;
|
|
@@ -1841,4 +1956,4 @@ declare const FetchResponse: z.ZodObject<{
|
|
|
1841
1956
|
}, z.core.$strict>;
|
|
1842
1957
|
type FetchResponse = z.infer<typeof FetchResponse>;
|
|
1843
1958
|
|
|
1844
|
-
export { AUDIENCES, Audience, BACKENDS, BACKEND_IDS, BackendClass, BackendCost, type BackendDescriptor, type BackendId, BackendIdSchema, Capability, CapabilityMatrix, ChatMessage, ChatPayload, ClaimRequest, ClaimResponse, ClaimedJob, ClaimedStub, DeliveredResult, ENCRYPTION_KEY_CONTEXT, ENDPOINTS, ENVELOPE_MAX_AGE_MS, ERROR_STATUS, type Endpoint, type EnvelopeContext, EnvelopeDirection, type EnvelopeFailure, FetchRequest, FetchResponse, GeneratePayload, HeartbeatRequest, HeartbeatResponse, JOB_KINDS, JobKind, JobOutcome, JobPayload, JobResultCanceled, JobResultError, JobResultOk, JobState, JobStub, KindedPayload, Lease, MAX_CLOCK_SKEW_MS, MIN_PROTOCOL_VERSION, MUSTS, MUST_IDS, type MatchDaemon, type MatchJob, MatchRefusal, type MatchResult, type Must, type MustEnforcer, type MustId, type MustVerification, type MustVerifiedBy, OFFER_SCOPES, OfferScope, type OpenResult, PAYLOAD_LIMITS, PROTOCOL_PREFIX, PROTOCOL_VERSION, PairPollRequest, PairPollResponse, PairRequest, PairStartRequest, PairStartResponse, type PayloadFor, PublicIdentity, REFUSAL_MESSAGES, ReleaseRequest, ReleaseResponse, RequestSignature, ResultDisposition, ResultProvenance, ResultRequest, ResultResponse, RunMetadata, SIZE_CLASS_LIMITS, SUPPORTED_PROTOCOL_VERSIONS, SealedEnvelope, SealedOutcome, type SignatureFailure, SizeClass, type SpendConsent, StoredKeys, TERMINAL_STATES, type VersionRefusal, WireError, WireErrorCode, backendDescriptor, canTransition, canonicalRequest, checkProtocolVersion, cryptoReady, declaredVersion, effectiveOfferScope, fingerprint, generateKeys, isBackendId, isJobKind, isLocalHost, isTerminal, keyId, kindsOf, matchAudience, mustsVerifiedBy, open, payloadTextLength, provenanceFor, publicIdentityOf, resolveCost, seal, signRequest, signSiteRequest, signWith, sizeClassCeiling, sizeClassOf, verifyPublicIdentity, verifyRequest, verifySiteRequest, verifyWith };
|
|
1959
|
+
export { AUDIENCES, Audience, BACKENDS, BACKEND_IDS, BackendClass, BackendCost, type BackendDescriptor, type BackendId, BackendIdSchema, Capability, CapabilityMatrix, ChatMessage, ChatPayload, ClaimRequest, ClaimResponse, ClaimedJob, ClaimedStub, DeliveredResult, ENCRYPTION_KEY_CONTEXT, ENDPOINTS, ENVELOPE_MAX_AGE_MS, ERROR_STATUS, type Endpoint, type EnvelopeContext, EnvelopeDirection, type EnvelopeFailure, FetchRequest, FetchResponse, GeneratePayload, HeartbeatRequest, HeartbeatResponse, JOB_KINDS, JobKind, JobOutcome, JobPayload, JobResultCanceled, JobResultError, JobResultOk, JobState, JobStub, KindedPayload, Lease, MAX_CLOCK_SKEW_MS, MAX_SUCCESSION_CHAIN, MIN_PROTOCOL_VERSION, MUSTS, MUST_IDS, type MatchDaemon, type MatchJob, MatchRefusal, type MatchResult, type Must, type MustEnforcer, type MustId, type MustVerification, type MustVerifiedBy, OFFER_SCOPES, OfferScope, type OpenResult, PAYLOAD_LIMITS, PROTOCOL_PREFIX, PROTOCOL_VERSION, PairPollRequest, PairPollResponse, PairRequest, PairStartRequest, PairStartResponse, type PayloadFor, PublicIdentity, REFUSAL_MESSAGES, RETIREMENT_WINDOW_MS, ReleaseRequest, ReleaseResponse, RequestSignature, ResultDisposition, ResultProvenance, ResultRequest, ResultResponse, RunMetadata, SIZE_CLASS_LIMITS, SUCCESSION_CONTEXT, SUPPORTED_PROTOCOL_VERSIONS, SealedEnvelope, SealedOutcome, type SignatureFailure, SizeClass, type SpendConsent, StoredKeys, Succession, type SuccessionFailure, type SuccessionWalk, TERMINAL_STATES, type VersionRefusal, WireError, WireErrorCode, backendDescriptor, canTransition, canonicalRequest, checkProtocolVersion, cryptoReady, declaredVersion, effectiveOfferScope, fingerprint, generateKeys, isBackendId, isJobKind, isLocalHost, isTerminal, keyId, kindsOf, matchAudience, mustsVerifiedBy, open, payloadTextLength, provenanceFor, publicIdentityOf, resolveCost, seal, signRequest, signSiteRequest, signSuccession, signWith, sizeClassCeiling, sizeClassOf, successionStatement, verifyLink, verifyPublicIdentity, verifyRequest, verifySiteRequest, verifyWith, walkSuccession };
|