@sentropic/h2a 0.2.4 → 0.2.6
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/envelope.d.ts +18 -0
- package/dist/envelope.d.ts.map +1 -1
- package/dist/envelope.js +42 -0
- package/dist/envelope.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/replay.d.ts +56 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +79 -0
- package/dist/replay.js.map +1 -0
- package/package.json +1 -1
package/dist/envelope.d.ts
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { type SignOptions } from "./signature.js";
|
|
1
2
|
import { type H2AEnvelope } from "./types.js";
|
|
2
3
|
type CreateEnvelopeInput<TBody> = Omit<H2AEnvelope<TBody>, "protocol" | "version" | "createdAt"> & {
|
|
3
4
|
createdAt?: string;
|
|
4
5
|
};
|
|
5
6
|
export declare function createEnvelope<TBody>(input: CreateEnvelopeInput<TBody>): H2AEnvelope<TBody>;
|
|
7
|
+
/**
|
|
8
|
+
* Sign an envelope's provenance (DEC-073). Returns a new envelope with the
|
|
9
|
+
* ed25519 signature appended to `signatures[]`; the original is not mutated.
|
|
10
|
+
* This is the "signed bearer" primitive underpinning authenticated transport
|
|
11
|
+
* (DEC-032): a recipient can verify *who* emitted an envelope independently of
|
|
12
|
+
* the channel it arrived on.
|
|
13
|
+
*/
|
|
14
|
+
export declare function signEnvelope<TBody>(envelope: H2AEnvelope<TBody>, options: SignOptions): H2AEnvelope<TBody>;
|
|
15
|
+
/**
|
|
16
|
+
* Verify an envelope's signature(s) against a public key (DEC-073). With
|
|
17
|
+
* `options.by`, only that signer's signature(s) are checked; otherwise any
|
|
18
|
+
* signature that verifies against the key counts. Returns false when the
|
|
19
|
+
* envelope carries no (matching) signature.
|
|
20
|
+
*/
|
|
21
|
+
export declare function verifyEnvelopeSignature<TBody>(envelope: H2AEnvelope<TBody>, publicKeyPem: string, options?: {
|
|
22
|
+
by?: string;
|
|
23
|
+
}): boolean;
|
|
6
24
|
export declare function isH2AEnvelope<TBody = unknown>(value: unknown): value is H2AEnvelope<TBody>;
|
|
7
25
|
export {};
|
|
8
26
|
//# sourceMappingURL=envelope.d.ts.map
|
package/dist/envelope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AAEpB,KAAK,mBAAmB,CAAC,KAAK,IAAI,IAAI,CACpC,WAAW,CAAC,KAAK,CAAC,EAClB,UAAU,GAAG,SAAS,GAAG,WAAW,CACrC,GAAG;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAwBF,wBAAgB,cAAc,CAAC,KAAK,EAClC,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAChC,WAAW,CAAC,KAAK,CAAC,CAOpB;AAED,wBAAgB,aAAa,CAAC,KAAK,GAAG,OAAO,EAC3C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC,CAc7B"}
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAML,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAC;AAEpB,KAAK,mBAAmB,CAAC,KAAK,IAAI,IAAI,CACpC,WAAW,CAAC,KAAK,CAAC,EAClB,UAAU,GAAG,SAAS,GAAG,WAAW,CACrC,GAAG;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAwBF,wBAAgB,cAAc,CAAC,KAAK,EAClC,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,GAChC,WAAW,CAAC,KAAK,CAAC,CAOpB;AAeD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAChC,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,EAC5B,OAAO,EAAE,WAAW,GACnB,WAAW,CAAC,KAAK,CAAC,CAMpB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAC3C,QAAQ,EAAE,WAAW,CAAC,KAAK,CAAC,EAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAO,GAC5B,OAAO,CAUT;AAED,wBAAgB,aAAa,CAAC,KAAK,GAAG,OAAO,EAC3C,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,WAAW,CAAC,KAAK,CAAC,CAc7B"}
|
package/dist/envelope.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { signCanonical, verifyCanonical } from "./signature.js";
|
|
1
2
|
import { H2A_ENVELOPE_TYPES, H2A_PROTOCOL, H2A_ROLES, H2A_VERSION } from "./types.js";
|
|
2
3
|
function isRecord(value) {
|
|
3
4
|
return typeof value === "object" && value !== null;
|
|
@@ -23,6 +24,47 @@ export function createEnvelope(input) {
|
|
|
23
24
|
...input
|
|
24
25
|
};
|
|
25
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* The portion of an envelope that a signature covers: everything except the
|
|
29
|
+
* `signatures` array itself. Excluding `signatures` makes the signed content
|
|
30
|
+
* stable, so multiple signers each sign the same provenance (DEC-073) — the
|
|
31
|
+
* same model as artifact signing (DEC-035).
|
|
32
|
+
*/
|
|
33
|
+
function envelopeSigningView(envelope) {
|
|
34
|
+
const { signatures: _omit, ...rest } = envelope;
|
|
35
|
+
return rest;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Sign an envelope's provenance (DEC-073). Returns a new envelope with the
|
|
39
|
+
* ed25519 signature appended to `signatures[]`; the original is not mutated.
|
|
40
|
+
* This is the "signed bearer" primitive underpinning authenticated transport
|
|
41
|
+
* (DEC-032): a recipient can verify *who* emitted an envelope independently of
|
|
42
|
+
* the channel it arrived on.
|
|
43
|
+
*/
|
|
44
|
+
export function signEnvelope(envelope, options) {
|
|
45
|
+
const signature = signCanonical(envelopeSigningView(envelope), options);
|
|
46
|
+
return {
|
|
47
|
+
...envelope,
|
|
48
|
+
signatures: [...(envelope.signatures ?? []), signature]
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Verify an envelope's signature(s) against a public key (DEC-073). With
|
|
53
|
+
* `options.by`, only that signer's signature(s) are checked; otherwise any
|
|
54
|
+
* signature that verifies against the key counts. Returns false when the
|
|
55
|
+
* envelope carries no (matching) signature.
|
|
56
|
+
*/
|
|
57
|
+
export function verifyEnvelopeSignature(envelope, publicKeyPem, options = {}) {
|
|
58
|
+
const signatures = envelope.signatures ?? [];
|
|
59
|
+
const candidates = options.by
|
|
60
|
+
? signatures.filter((s) => s.by === options.by)
|
|
61
|
+
: signatures;
|
|
62
|
+
if (candidates.length === 0) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const view = envelopeSigningView(envelope);
|
|
66
|
+
return candidates.some((sig) => verifyCanonical(view, sig, publicKeyPem));
|
|
67
|
+
}
|
|
26
68
|
export function isH2AEnvelope(value) {
|
|
27
69
|
if (!isRecord(value)) {
|
|
28
70
|
return false;
|
package/dist/envelope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,WAAW,EAIZ,MAAM,YAAY,CAAC;AASpB,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,kBAAkB,CAAC,QAAQ,CAAC,KAAwB,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAClC,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAC/B,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,IAA2B,CAAC;QACrD,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CACnE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAAiC;IAEjC,OAAO;QACL,QAAQ,EAAE,YAAY;QACtB,OAAO,EAAE,WAAW;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtD,GAAG,KAAK;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAc;IAEd,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,KAAK,CAAC,QAAQ,KAAK,YAAY;QAC/B,KAAK,CAAC,OAAO,KAAK,WAAW;QAC7B,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;QAC5B,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC;QAC1B,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC;QACvB,MAAM,IAAI,KAAK;QACf,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CACpC,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,9 @@ export { H2A_OBLIGATION_CADENCES, H2A_RECURRING_OBLIGATION_CONFLICT_DISPOSITIONS
|
|
|
14
14
|
export type { H2AObligationCadence, H2ARecurringObligationAuditResult, H2ARecurringObligationConflictDisposition, H2ARecurringObligationProfileDescriptor } from "./recurring-obligations.js";
|
|
15
15
|
export { H2A_JURISDICTION_CONFLICT_DISPOSITIONS, H2A_JURISDICTION_KINDS, H2A_JURISDICTION_PROFILES, auditJurisdictionProfile, getJurisdictionProfile } from "./jurisdiction.js";
|
|
16
16
|
export type { H2AJurisdictionAuditResult, H2AJurisdictionConflictDisposition, H2AJurisdictionKind, H2AJurisdictionProfileDescriptor } from "./jurisdiction.js";
|
|
17
|
-
export { createEnvelope, isH2AEnvelope } from "./envelope.js";
|
|
17
|
+
export { createEnvelope, isH2AEnvelope, signEnvelope, verifyEnvelopeSignature } from "./envelope.js";
|
|
18
|
+
export { H2A_DEFAULT_MAX_AGE_MS, H2A_DEFAULT_MAX_SKEW_MS, checkEnvelopeFreshness, createReplayGuard } from "./replay.js";
|
|
19
|
+
export type { H2AFreshnessOptions, H2AReplayCheck, H2AReplayGuard, H2AReplayRejection } from "./replay.js";
|
|
18
20
|
export { H2A_SESSION_DEFAULT_EXPIRY_MS, H2A_SESSION_DEFAULT_HEARTBEAT_INTERVAL_MS, H2A_SESSION_NOTIFICATION_TOPICS, H2A_SESSION_STATES, isH2ASession, isSessionExpired, pickFreshSessions } from "./session.js";
|
|
19
21
|
export type { H2ASession, H2ASessionExpiryOptions, H2ASessionInterests, H2ASessionNotificationTopic, H2ASessionState } from "./session.js";
|
|
20
22
|
export { H2A_HOST_BRIDGE_CLAUSES, H2A_HOST_BRIDGE_PROFILES, auditHostBridge, getHostBridgeProfile, listHostBridgeProfiles } from "./h2a-bridge.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,qBAAqB,EACrB,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,EAC9B,aAAa,EACb,4BAA4B,EAC5B,cAAc,EACd,WAAW,EACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACnB,wBAAwB,EACxB,0BAA0B,EAC1B,iCAAiC,EACjC,gCAAgC,EACjC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,mCAAmC,EACnC,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,2CAA2C,EAC3C,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,8BAA8B,EAC9B,sCAAsC,EACtC,oCAAoC,EACpC,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,oCAAoC,EACpC,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,wBAAwB,EACxB,gCAAgC,EAChC,iBAAiB,EACjB,8BAA8B,EAC/B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,sBAAsB,EACtB,8BAA8B,EAC9B,4BAA4B,EAC5B,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,uBAAuB,EACvB,8CAA8C,EAC9C,iCAAiC,EACjC,+BAA+B,EAC/B,6BAA6B,EAC9B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,oBAAoB,EACpB,iCAAiC,EACjC,yCAAyC,EACzC,uCAAuC,EACxC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,sCAAsC,EACtC,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,0BAA0B,EAC1B,kCAAkC,EAClC,mBAAmB,EACnB,gCAAgC,EACjC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,8 @@ export { H2A_DISCLOSURE_CONFLICT_DISPOSITIONS, H2A_DISCLOSURE_MODES, H2A_DISCLOS
|
|
|
6
6
|
export { H2A_RECOURSE_CONFLICT_DISPOSITIONS, H2A_RECOURSE_PROFILES, H2A_RECOURSE_STATES, auditRecourseProfile, getRecourseProfile } from "./recourse.js";
|
|
7
7
|
export { H2A_OBLIGATION_CADENCES, H2A_RECURRING_OBLIGATION_CONFLICT_DISPOSITIONS, H2A_RECURRING_OBLIGATION_PROFILES, auditRecurringObligationProfile, getRecurringObligationProfile } from "./recurring-obligations.js";
|
|
8
8
|
export { H2A_JURISDICTION_CONFLICT_DISPOSITIONS, H2A_JURISDICTION_KINDS, H2A_JURISDICTION_PROFILES, auditJurisdictionProfile, getJurisdictionProfile } from "./jurisdiction.js";
|
|
9
|
-
export { createEnvelope, isH2AEnvelope } from "./envelope.js";
|
|
9
|
+
export { createEnvelope, isH2AEnvelope, signEnvelope, verifyEnvelopeSignature } from "./envelope.js";
|
|
10
|
+
export { H2A_DEFAULT_MAX_AGE_MS, H2A_DEFAULT_MAX_SKEW_MS, checkEnvelopeFreshness, createReplayGuard } from "./replay.js";
|
|
10
11
|
export { H2A_SESSION_DEFAULT_EXPIRY_MS, H2A_SESSION_DEFAULT_HEARTBEAT_INTERVAL_MS, H2A_SESSION_NOTIFICATION_TOPICS, H2A_SESSION_STATES, isH2ASession, isSessionExpired, pickFreshSessions } from "./session.js";
|
|
11
12
|
export { H2A_HOST_BRIDGE_CLAUSES, H2A_HOST_BRIDGE_PROFILES, auditHostBridge, getHostBridgeProfile, listHostBridgeProfiles } from "./h2a-bridge.js";
|
|
12
13
|
export { assertValidNegotiationState } from "./negotiation.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,EAC1B,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAWlB,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAU1B,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC5B,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EACL,2CAA2C,EAC3C,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EACL,oCAAoC,EACpC,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,iBAAiB,CAAC;AAOzB,OAAO,EACL,kCAAkC,EAClC,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAOvB,OAAO,EACL,uBAAuB,EACvB,8CAA8C,EAC9C,iCAAiC,EACjC,+BAA+B,EAC/B,6BAA6B,EAC9B,MAAM,4BAA4B,CAAC;AAOpC,OAAO,EACL,sCAAsC,EACtC,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EACL,cAAc,EACd,aAAa,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/replay.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anti-replay for signed envelopes (DEC-074), slice 2 of the signed-bearer
|
|
3
|
+
* transport-auth workstream (DEC-032 / DEC-073).
|
|
4
|
+
*
|
|
5
|
+
* A DEC-073 signature proves *who* emitted an envelope, but not that it is
|
|
6
|
+
* *fresh* — a validly signed envelope can be captured and re-sent. Replay
|
|
7
|
+
* protection adds two orthogonal checks:
|
|
8
|
+
*
|
|
9
|
+
* - **Freshness**: the envelope's `createdAt` must fall inside an accepted
|
|
10
|
+
* window `[now - maxAgeMs, now + maxSkewMs]` (skew tolerates clock drift on
|
|
11
|
+
* the emitter).
|
|
12
|
+
* - **Dedup**: the envelope's `id` must not have been accepted before. The
|
|
13
|
+
* `id` is part of the signed view (DEC-073), so a replayed envelope carries
|
|
14
|
+
* the same id and is rejected.
|
|
15
|
+
*
|
|
16
|
+
* Both are pure/in-memory — no I/O — so this lives in `@sentropic/h2a`. The
|
|
17
|
+
* channel that moves bytes is irrelevant; verification is end-to-end.
|
|
18
|
+
*/
|
|
19
|
+
import type { H2AEnvelope } from "./types.js";
|
|
20
|
+
export declare const H2A_DEFAULT_MAX_AGE_MS = 300000;
|
|
21
|
+
export declare const H2A_DEFAULT_MAX_SKEW_MS = 60000;
|
|
22
|
+
export interface H2AFreshnessOptions {
|
|
23
|
+
/** Reference time (ms epoch). Defaults to `Date.now()`. */
|
|
24
|
+
now?: number;
|
|
25
|
+
/** How old an envelope may be before it is stale. Default 5 min. */
|
|
26
|
+
maxAgeMs?: number;
|
|
27
|
+
/** How far in the future `createdAt` may be (clock skew). Default 1 min. */
|
|
28
|
+
maxSkewMs?: number;
|
|
29
|
+
}
|
|
30
|
+
export type H2AReplayRejection = "invalid-timestamp" | "expired" | "future" | "replayed";
|
|
31
|
+
export interface H2AReplayCheck {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
reason?: H2AReplayRejection;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Pure freshness check: is the envelope's `createdAt` within the accepted
|
|
37
|
+
* window? Does not consider dedup (that needs state — see {@link createReplayGuard}).
|
|
38
|
+
*/
|
|
39
|
+
export declare function checkEnvelopeFreshness(envelope: H2AEnvelope, options?: H2AFreshnessOptions): H2AReplayCheck;
|
|
40
|
+
export interface H2AReplayGuard {
|
|
41
|
+
/**
|
|
42
|
+
* Accept an envelope iff it is fresh AND its id has not been seen before.
|
|
43
|
+
* On success the id is remembered for the rest of its freshness window.
|
|
44
|
+
*/
|
|
45
|
+
accept(envelope: H2AEnvelope, now?: number): H2AReplayCheck;
|
|
46
|
+
/** Number of remembered ids (after pruning). Mostly for tests/observability. */
|
|
47
|
+
size(): number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create an in-memory replay guard. It remembers accepted envelope ids until
|
|
51
|
+
* they fall out of the freshness window, so the set stays bounded: an id that
|
|
52
|
+
* could only be replayed *after* it has expired would be rejected by the
|
|
53
|
+
* freshness check anyway, so it is safe to forget.
|
|
54
|
+
*/
|
|
55
|
+
export declare function createReplayGuard(options?: Pick<H2AFreshnessOptions, "maxAgeMs" | "maxSkewMs">): H2AReplayGuard;
|
|
56
|
+
//# sourceMappingURL=replay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,sBAAsB,SAAU,CAAC;AAC9C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEzF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,mBAAwB,GAChC,cAAc,CAgBhB;AAED,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAC5D,gFAAgF;IAChF,IAAI,IAAI,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,GAAG,WAAW,CAAM,GAChE,cAAc,CAgChB"}
|
package/dist/replay.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anti-replay for signed envelopes (DEC-074), slice 2 of the signed-bearer
|
|
3
|
+
* transport-auth workstream (DEC-032 / DEC-073).
|
|
4
|
+
*
|
|
5
|
+
* A DEC-073 signature proves *who* emitted an envelope, but not that it is
|
|
6
|
+
* *fresh* — a validly signed envelope can be captured and re-sent. Replay
|
|
7
|
+
* protection adds two orthogonal checks:
|
|
8
|
+
*
|
|
9
|
+
* - **Freshness**: the envelope's `createdAt` must fall inside an accepted
|
|
10
|
+
* window `[now - maxAgeMs, now + maxSkewMs]` (skew tolerates clock drift on
|
|
11
|
+
* the emitter).
|
|
12
|
+
* - **Dedup**: the envelope's `id` must not have been accepted before. The
|
|
13
|
+
* `id` is part of the signed view (DEC-073), so a replayed envelope carries
|
|
14
|
+
* the same id and is rejected.
|
|
15
|
+
*
|
|
16
|
+
* Both are pure/in-memory — no I/O — so this lives in `@sentropic/h2a`. The
|
|
17
|
+
* channel that moves bytes is irrelevant; verification is end-to-end.
|
|
18
|
+
*/
|
|
19
|
+
export const H2A_DEFAULT_MAX_AGE_MS = 300_000; // 5 minutes
|
|
20
|
+
export const H2A_DEFAULT_MAX_SKEW_MS = 60_000; // 1 minute clock skew
|
|
21
|
+
/**
|
|
22
|
+
* Pure freshness check: is the envelope's `createdAt` within the accepted
|
|
23
|
+
* window? Does not consider dedup (that needs state — see {@link createReplayGuard}).
|
|
24
|
+
*/
|
|
25
|
+
export function checkEnvelopeFreshness(envelope, options = {}) {
|
|
26
|
+
const now = options.now ?? Date.now();
|
|
27
|
+
const maxAgeMs = options.maxAgeMs ?? H2A_DEFAULT_MAX_AGE_MS;
|
|
28
|
+
const maxSkewMs = options.maxSkewMs ?? H2A_DEFAULT_MAX_SKEW_MS;
|
|
29
|
+
const created = Date.parse(envelope.createdAt);
|
|
30
|
+
if (Number.isNaN(created)) {
|
|
31
|
+
return { ok: false, reason: "invalid-timestamp" };
|
|
32
|
+
}
|
|
33
|
+
if (created > now + maxSkewMs) {
|
|
34
|
+
return { ok: false, reason: "future" };
|
|
35
|
+
}
|
|
36
|
+
if (created < now - maxAgeMs) {
|
|
37
|
+
return { ok: false, reason: "expired" };
|
|
38
|
+
}
|
|
39
|
+
return { ok: true };
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create an in-memory replay guard. It remembers accepted envelope ids until
|
|
43
|
+
* they fall out of the freshness window, so the set stays bounded: an id that
|
|
44
|
+
* could only be replayed *after* it has expired would be rejected by the
|
|
45
|
+
* freshness check anyway, so it is safe to forget.
|
|
46
|
+
*/
|
|
47
|
+
export function createReplayGuard(options = {}) {
|
|
48
|
+
const maxAgeMs = options.maxAgeMs ?? H2A_DEFAULT_MAX_AGE_MS;
|
|
49
|
+
const maxSkewMs = options.maxSkewMs ?? H2A_DEFAULT_MAX_SKEW_MS;
|
|
50
|
+
// id -> the createdAt (ms) we accepted it at, for window-based pruning.
|
|
51
|
+
const seen = new Map();
|
|
52
|
+
function prune(now) {
|
|
53
|
+
for (const [id, created] of seen) {
|
|
54
|
+
if (created < now - maxAgeMs)
|
|
55
|
+
seen.delete(id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
accept(envelope, now = Date.now()) {
|
|
60
|
+
const freshness = checkEnvelopeFreshness(envelope, {
|
|
61
|
+
now,
|
|
62
|
+
maxAgeMs,
|
|
63
|
+
maxSkewMs
|
|
64
|
+
});
|
|
65
|
+
if (!freshness.ok)
|
|
66
|
+
return freshness;
|
|
67
|
+
prune(now);
|
|
68
|
+
if (seen.has(envelope.id)) {
|
|
69
|
+
return { ok: false, reason: "replayed" };
|
|
70
|
+
}
|
|
71
|
+
seen.set(envelope.id, Date.parse(envelope.createdAt));
|
|
72
|
+
return { ok: true };
|
|
73
|
+
},
|
|
74
|
+
size() {
|
|
75
|
+
return seen.size;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=replay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replay.js","sourceRoot":"","sources":["../src/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,CAAC,YAAY;AAC3D,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC,CAAC,sBAAsB;AAkBrE;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAqB,EACrB,UAA+B,EAAE;IAEjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,sBAAsB,CAAC;IAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,uBAAuB,CAAC;IAE/D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,GAAG,GAAG,GAAG,SAAS,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,GAAG,GAAG,GAAG,QAAQ,EAAE,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAYD;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAA+D,EAAE;IAEjE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,sBAAsB,CAAC;IAC5D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,uBAAuB,CAAC;IAC/D,wEAAwE;IACxE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvC,SAAS,KAAK,CAAC,GAAW;QACxB,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;YACjC,IAAI,OAAO,GAAG,GAAG,GAAG,QAAQ;gBAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO;QACL,MAAM,CAAC,QAAqB,EAAE,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;YAC5C,MAAM,SAAS,GAAG,sBAAsB,CAAC,QAAQ,EAAE;gBACjD,GAAG;gBACH,QAAQ;gBACR,SAAS;aACV,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,CAAC,EAAE;gBAAE,OAAO,SAAS,CAAC;YAEpC,KAAK,CAAC,GAAG,CAAC,CAAC;YACX,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC1B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YAC3C,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;YACtD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;QACD,IAAI;YACF,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC"}
|