@request-seal/core 0.0.0-stage → 0.1.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/CHANGELOG.md +71 -0
- package/LICENSE +190 -0
- package/NOTICE +9 -0
- package/README.md +164 -2
- package/dist/accept-signature.d.ts +26 -0
- package/dist/accept-signature.js +225 -0
- package/dist/adapters/fetch/index.d.ts +33 -0
- package/dist/adapters/fetch/index.js +438 -0
- package/dist/adapters/fetch/runtime.d.ts +10 -0
- package/dist/adapters/fetch/runtime.js +33 -0
- package/dist/adapters/node-http/index.d.ts +70 -0
- package/dist/adapters/node-http/index.js +878 -0
- package/dist/adapters/support.d.ts +27 -0
- package/dist/adapters/support.js +193 -0
- package/dist/brand.d.ts +8 -0
- package/dist/brand.js +70 -0
- package/dist/bytes.d.ts +7 -0
- package/dist/bytes.js +71 -0
- package/dist/constants.d.ts +72 -0
- package/dist/constants.js +59 -0
- package/dist/context.d.ts +19 -0
- package/dist/context.js +192 -0
- package/dist/crypto/algorithm.d.ts +36 -0
- package/dist/crypto/algorithm.js +147 -0
- package/dist/crypto/index.d.ts +9 -0
- package/dist/crypto/index.js +75 -0
- package/dist/crypto/jose.d.ts +9 -0
- package/dist/crypto/jose.js +45 -0
- package/dist/crypto/primitive.d.ts +6 -0
- package/dist/crypto/primitive.js +95 -0
- package/dist/crypto/subtle.d.ts +22 -0
- package/dist/crypto/subtle.js +13 -0
- package/dist/custody/content_key.d.ts +9 -0
- package/dist/custody/content_key.js +99 -0
- package/dist/custody/der.d.ts +36 -0
- package/dist/custody/der.js +530 -0
- package/dist/custody/index.d.ts +4 -0
- package/dist/custody/index.js +2 -0
- package/dist/custody/jwk.d.ts +10 -0
- package/dist/custody/jwk.js +211 -0
- package/dist/custody/local.d.ts +4 -0
- package/dist/custody/local.js +277 -0
- package/dist/custody/ssh-agent/index.d.ts +7 -0
- package/dist/custody/ssh-agent/index.js +228 -0
- package/dist/custody/ssh-agent/wire.d.ts +17 -0
- package/dist/custody/ssh-agent/wire.js +140 -0
- package/dist/digest.d.ts +42 -0
- package/dist/digest.js +370 -0
- package/dist/discovery/address.d.ts +10 -0
- package/dist/discovery/address.js +105 -0
- package/dist/discovery/body.d.ts +40 -0
- package/dist/discovery/body.js +191 -0
- package/dist/discovery/cache.d.ts +17 -0
- package/dist/discovery/cache.js +235 -0
- package/dist/discovery/certificate.d.ts +3 -0
- package/dist/discovery/certificate.js +81 -0
- package/dist/discovery/deflate.d.ts +5 -0
- package/dist/discovery/deflate.js +140 -0
- package/dist/discovery/gzip.d.ts +3 -0
- package/dist/discovery/gzip.js +97 -0
- package/dist/discovery/headers.d.ts +9 -0
- package/dist/discovery/headers.js +119 -0
- package/dist/discovery/index.d.ts +17 -0
- package/dist/discovery/index.js +51 -0
- package/dist/discovery/node-connection.d.ts +7 -0
- package/dist/discovery/node-connection.js +12 -0
- package/dist/discovery/node.d.ts +15 -0
- package/dist/discovery/node.js +459 -0
- package/dist/discovery/proof.d.ts +9 -0
- package/dist/discovery/proof.js +162 -0
- package/dist/discovery/snapshot.d.ts +9 -0
- package/dist/discovery/snapshot.js +73 -0
- package/dist/discovery/source.d.ts +35 -0
- package/dist/discovery/source.js +199 -0
- package/dist/discovery/support.d.ts +13 -0
- package/dist/discovery/support.js +62 -0
- package/dist/errors/parity.d.ts +1894 -0
- package/dist/errors/parity.js +2119 -0
- package/dist/errors/types.d.ts +81 -0
- package/dist/errors/types.js +61 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +35 -0
- package/dist/jose/header.d.ts +23 -0
- package/dist/jose/header.js +231 -0
- package/dist/jose/jwe.d.ts +24 -0
- package/dist/jose/jwe.js +255 -0
- package/dist/jose/jws.d.ts +24 -0
- package/dist/jose/jws.js +191 -0
- package/dist/jose/key-management.d.ts +30 -0
- package/dist/jose/key-management.js +265 -0
- package/dist/jose/nested.d.ts +14 -0
- package/dist/jose/nested.js +55 -0
- package/dist/jose/support.d.ts +26 -0
- package/dist/jose/support.js +143 -0
- package/dist/json.d.ts +33 -0
- package/dist/json.js +281 -0
- package/dist/key_handle.d.ts +21 -0
- package/dist/key_handle.js +256 -0
- package/dist/key_identity.d.ts +17 -0
- package/dist/key_identity.js +77 -0
- package/dist/message/index.d.ts +60 -0
- package/dist/message/index.js +355 -0
- package/dist/node_hasher.d.ts +4 -0
- package/dist/node_hasher.js +26 -0
- package/dist/numbers.d.ts +12 -0
- package/dist/numbers.js +24 -0
- package/dist/policy.d.ts +55 -0
- package/dist/policy.js +174 -0
- package/dist/public_key.d.ts +23 -0
- package/dist/public_key.js +156 -0
- package/dist/quorum/evaluation.d.ts +22 -0
- package/dist/quorum/evaluation.js +384 -0
- package/dist/quorum/verification.d.ts +36 -0
- package/dist/quorum/verification.js +84 -0
- package/dist/quorum.d.ts +39 -0
- package/dist/quorum.js +145 -0
- package/dist/replay/claim.d.ts +19 -0
- package/dist/replay/claim.js +71 -0
- package/dist/replay/index.d.ts +12 -0
- package/dist/replay/index.js +6 -0
- package/dist/replay/memory.d.ts +4 -0
- package/dist/replay/memory.js +46 -0
- package/dist/replay/postgres.d.ts +10 -0
- package/dist/replay/postgres.js +63 -0
- package/dist/replay/receipt.d.ts +4 -0
- package/dist/replay/receipt.js +22 -0
- package/dist/replay/store.d.ts +9 -0
- package/dist/replay/store.js +67 -0
- package/dist/replay-port.d.ts +36 -0
- package/dist/replay-port.js +1 -0
- package/dist/result.d.ts +10 -0
- package/dist/result.js +7 -0
- package/dist/runtime.d.ts +7 -0
- package/dist/runtime.js +23 -0
- package/dist/sign.d.ts +34 -0
- package/dist/sign.js +313 -0
- package/dist/signature-base/index.d.ts +6 -0
- package/dist/signature-base/index.js +320 -0
- package/dist/signature-fields.d.ts +25 -0
- package/dist/signature-fields.js +160 -0
- package/dist/signer.d.ts +7 -0
- package/dist/signer.js +16 -0
- package/dist/structured-fields/index.d.ts +78 -0
- package/dist/structured-fields/index.js +658 -0
- package/dist/verification.d.ts +33 -0
- package/dist/verification.js +152 -0
- package/dist/verify-quorum.d.ts +3 -0
- package/dist/verify-quorum.js +144 -0
- package/dist/verify.d.ts +25 -0
- package/dist/verify.js +388 -0
- package/dist/web-bot-auth/index.d.ts +13 -0
- package/dist/web-bot-auth/index.js +10 -0
- package/dist/web-bot-auth/policy.d.ts +33 -0
- package/dist/web-bot-auth/policy.js +106 -0
- package/dist/web-bot-auth/sign.d.ts +3 -0
- package/dist/web-bot-auth/sign.js +121 -0
- package/dist/web-bot-auth/support.d.ts +16 -0
- package/dist/web-bot-auth/support.js +157 -0
- package/dist/web-bot-auth/verification.d.ts +56 -0
- package/dist/web-bot-auth/verification.js +50 -0
- package/dist/web-bot-auth/verify.d.ts +3 -0
- package/dist/web-bot-auth/verify.js +345 -0
- package/package.json +77 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Align HTTP handle signing and the error vocabulary with RequestSeal 0.4.0: explicit `signingTimeout` bounds, `signer_algorithm_mismatch` with its exact message, and `signing_failed` with a bounded custody source on both forms. Handle deadlines start immediately before custody, after signature-base construction, and are capped at `signingTimeout` (default 5,000 ms) even under a longer caller Context. Generated-spec KeyHandle failures now report `signing_failed` (previously `signer_failed`); direct `handle.sign` malformed output now reports `invalid_signing_output` (previously `custodian_failure`). Add nullable core `message` and `source` fields; preserve callable `signer_failed` behavior. Re-pin the error extraction, shared corpus, and replay peer.
|
|
6
|
+
- Rename the npm package from `request-seal` to `@request-seal/core` under the `request-seal` organization; use `@request-seal/core/<subpath>` for every subpath import.
|
|
7
|
+
- Add captured Node HTTP Web Bot Auth verification, shared attempt storage, and executable signed TLS directory examples.
|
|
8
|
+
- Reject concurrent capture consumers and retained length mismatches; derive HTTP/2 scheme from TLS and reject conflicting Host/authority.
|
|
9
|
+
- Add captured-request quorum verification with shared replay and single-verification guards.
|
|
10
|
+
- Apply redirect method/body rules, validate redirect policy before delivery, remove Location fragments, and report actual client attempts.
|
|
11
|
+
- Measure Fetch runtime overrides and eligibility in the wire lane; refuse Node sec-fetch-mode signing, empty-query targets on Node majors below 24, and planted runtime markers.
|
|
12
|
+
- Deliver response signatures with their exact buffered bytes, use one clock for Date and created, and omit prohibited lengths.
|
|
13
|
+
- Require absolute ssh-agent sockets and preserve connection error parity; execute every README TypeScript fence against real inputs.
|
|
14
|
+
- Validate literal discovery addresses before deadline dispatch; restore replay timer coverage beside caller cancellation and cap built-test concurrency at 4.
|
|
15
|
+
- Add optional Node HTTP capture/replay, final response signing, bounded signed clients, Fetch signing and runtime-restricted verification, and caller-selected OpenSSH agent custody. Record exact Node/Deno/Bun wire observations and generated-key OpenSSL checks.
|
|
16
|
+
- Hold the process only while a run is active: each run arms its own referenced deadline timer, so a run whose only pending work is a caller callback that never settles ends with `deadline_exceeded` at its deadline on Node, Deno and Bun instead of being dropped; idle and settled Contexts never keep a process alive; pass a Context signal to stop sooner.
|
|
17
|
+
- Reject foreign `err()` and `adapterError` payloads with `TypeError`; accept any callable signer or KeyHandle for Accept-Signature fulfillment (an intentional divergence from the reference's two-argument function); permit shared stateless digest factories while rejecting overlapping operations on one session; check fetched cache results against their fetch clock and snapshots against the cache clock; decode every query key eagerly and classify TLS failures as the reference does; avoid idle timers for signal-free contexts and reattach cancellation listeners on reuse after internal release.
|
|
18
|
+
- Redact every individual Verification in JSON and runtime inspection while preserving explicit canonical facts; accept callable signers, trust callbacks, and held-key resolvers without Function.length gates, including KeyHandle signing.
|
|
19
|
+
- Document Web Bot Auth deadline phases, held-key fallback conditions, coverage-only nested evidence, host normalization differences, and generic principal narrowing. Verify origin confinement against two real loopback TLS peers.
|
|
20
|
+
- Add source-bound Web Bot Auth protocol-00 signing and verification, trusted agent provenance, nested coverage evidence, and one profile-separated envelope replay claim.
|
|
21
|
+
- Execute all fourteen Web Bot Auth corpus cases; preserve published bytes and rejection expectations. Add real signed TLS directory rotation/removal, OpenSSL byte agreement, and counting-store checks.
|
|
22
|
+
- Permit explicit JOSE algorithm choices in discovery lookup while retaining key metadata restrictions; apply replay retention ceilings after the complete envelope's earliest end.
|
|
23
|
+
- Match reference quorum assignment search and tie-breaking, check bindings incrementally and yield after about 10 ms of search work, and merge canonical identities with union-find.
|
|
24
|
+
- Parse quorum signature dictionaries once, cache per-label bases by field schema, enforce asymmetric handle identity consistency when observed or supplied, and preserve configured failure order.
|
|
25
|
+
- Align replay rejection, Accept-Signature validation precedence and reference string normalization; add caller-owned ordered fulfillment and redact quorum policies and composite results in JSON inspection; preserve custody deadlines during fulfillment.
|
|
26
|
+
- Executed differential coverage: 2,160 count-only instances from the original brute force (any mode, up to 5 slots), plus 2,160 instances checked on assignments and reasons with bindings, merged and unknown identities, all modes and units, and 8 to 16 slots. The 14 recorded divergence cases are checked against the reference port.
|
|
27
|
+
- Add branded quorum policies, identity-aware assignment with bounded exact search, nested and same-parameter bindings, and independent single-label verification facts.
|
|
28
|
+
- Add RFC 9421 Accept-Signature parsing and verified-pool challenge matching; execute all three quorum and negotiation corpus cases.
|
|
29
|
+
- Keep Context ownership release internal, align safe-number receipt bounds with claims, and reject corpus receipt/claim retention disagreements. Document required-content deadlines and verify-produced number ends.
|
|
30
|
+
- Normalize caller replay store errors, accept the exact signed bigint retention lower bound, release replay child Context listeners, and preserve deadline_exceeded during required content checks.
|
|
31
|
+
- Keep receipt construction internal, verify the packed PostgreSQL export, and require the real database URL in CI. PostgreSQL cross-language checks run where REQUESTSEAL_REPLAY_ELIXIR=1 and an Elixir toolchain with the pinned dependencies are present; the CI Elixir lane is separate work.
|
|
32
|
+
- Add branded replay claims and receipts, shared exclusive retention arithmetic, a bounded single-isolate memory store, and the dependency-free replay-postgres subpath over caller-owned autocommit queries.
|
|
33
|
+
- Execute all eleven v0.3.1 replay.claim cases, add a verbatim replay smoke case, and pass Context cancellation to the store while preventing a late commitment from reaching storage.
|
|
34
|
+
- Add bounded compact JWS signing and verification, JWE encryption and authenticated decryption, one-level nesting, explicit policy snapshots, and separately branded results.
|
|
35
|
+
- Add confined JOSE key-management capabilities, unconditional random fallback on unwrap failure, OAEP uniform-error tests and timing measurements, and reciprocal OpenSSL checks for RSA-OAEP (SHA-1 and SHA-256), A128GCMKW and A256GCMKW (empty AAD), and direct A128GCM and A256GCM in both directions.
|
|
36
|
+
- Execute all v0.3.1 JWS/JWE cases and both JOSE Wycheproof batches; retain source verdicts, declared overrides, applicability counts, and the two exact Bun ECDSA limitations.
|
|
37
|
+
- Re-pin error parity to RequestSeal v0.3.1 (commit b0d6f94); add `retention_exceeded` before replay commitment and storage when the retention end exceeds the clock bound.
|
|
38
|
+
- Add explicit generic signing and verification, frozen policies and layered verifications, canonical fact serialization, and a caller-owned replay port.
|
|
39
|
+
- Add RFC 9530 digests, bounded incremental SHA-2 with construction self-tests, and the Node-compatible hasher subpath.
|
|
40
|
+
- Execute the shared signing and verification corpus and add a tooling smoke case for each new surface.
|
|
41
|
+
- Preserve the discovery Node source type in built exports; refuse OS trust when Node has no non-empty system CA list. Retain cache rollback history through no-store, expiry and invalidation, and count CRLF within the chunk-line limit.
|
|
42
|
+
- Run live corpus vendoring when offline mode is unset, independently of gh; align Deno permissions and extract error rules directly from the pinned commit.
|
|
43
|
+
- Add bounded discovery sources, JWKS/directory/CIMD snapshots, directory possession proofs, source-bound key sets and resolutions, caller-owned caches, and the resolver bridge.
|
|
44
|
+
- Add the `./discovery-node` HTTPS transport with pinned-address TLS connections, IANA address denial, exact exceptions, manual redirects, proxy exclusion, cancellation, and body/decompression ceilings.
|
|
45
|
+
- All four `discovery.body` cases execute from the unchanged v0.3.1 corpus: 2,979 executed or runtime-limited items, 62 not applicable, and 23 pending out of 3,064; add real TLS, DNS, proxy, rotation and removal probes.
|
|
46
|
+
- Add captured WebCrypto primitives, separate HTTP/JWS registries, fixed RSA-PSS parameters, and fixed-width ECDSA and canonical Ed25519 verification.
|
|
47
|
+
- Add bounded DER/PEM codecs, validated RSA CRT import, private local key handles, public key formats and thumbprints, opaque identities, deadline containment, and confined RSA-OAEP/AES capabilities.
|
|
48
|
+
- Add pinned RFC and Wycheproof vectors, OpenSSL reciprocity, crypto/key corpus surfaces, batch counts and overrides, canary checks, and HMAC timing measurements.
|
|
49
|
+
- Keep deadline contexts reusable across nested and sequential runs; settlement releases only the active run, and idle contexts without caller or parent signals do not arm timers.
|
|
50
|
+
- Bound JOSE deadline error parity to the crypto layer and reject invalid adapter constructor arguments with TypeError.
|
|
51
|
+
- Add the ESM package scaffold, strict TypeScript build, web-only core typecheck, Node runtime lanes, Deno and Bun core lanes, and staged trusted-publishing workflow.
|
|
52
|
+
- Add Result and eleven bounded error variants with parity against Elixir RequestSeal v0.3.1 (commit b0d6f94), including status-derived discovery retryability.
|
|
53
|
+
- Add copied ByteString inputs, strict base64/base64url, ordered bounded I-JSON with exact number lexemes, and RFC numeric guards.
|
|
54
|
+
- Add branded deadline contexts, callback fault containment, deep freezing, and own-key option snapshots.
|
|
55
|
+
- Add the corpus loader, checksummed three-case tooling corpus, CLI, tamper checks, self-checks, and package boundary validation.
|
|
56
|
+
- Run live corpus vendoring when gh is available and offline mode is unset; align Deno permissions and extract error rules directly from the pinned commit.
|
|
57
|
+
- All four `discovery.body` cases execute from the unchanged v0.3.1 corpus: 2,965 executed or runtime-limited items, 62 not applicable, and 37 pending out of 3,064; add real TLS, DNS, proxy, rotation and removal probes.
|
|
58
|
+
- Keep deadline contexts reusable across nested and sequential runs; settlement releases only the active run, and idle contexts do not arm timers.
|
|
59
|
+
- Move the corpus pin to RequestSeal v0.3.1, index SHA-256 `222bae05fe7a240c6457ec02659e39f1785629290c7883dca404dd21d71f0398` (verified by `scripts/vendor-corpus.ts v0.3.1 --update-pin`).
|
|
60
|
+
- Vendor the checksummed RequestSeal v0.3.0 conformance corpus; pin its release commit and index digest. Validate batch inventories, per-item pins and overrides, positive references, and execution counts. Report pending surfaces against a committed allowlist during development and block releases until complete coverage. Wycheproof overrides are declared pins with cited clauses and may replace valid, invalid, or acceptable published verdicts; HTTPWG and RFC 9421 batches reject overrides.
|
|
61
|
+
- Require an explicit schema for Structured Fields parsing and caller-built tree serialization; parsed trees retain their schema. Revision strings disable inner lists unless a schema enables them.
|
|
62
|
+
- Add parseField with ordered occurrence combination, selective uniqueKeys, and independent uniqueParameters policies.
|
|
63
|
+
- Require RFC 3986 IPv6 or IPvFuture bracketed authorities; reject bracketed IPv4 forms and zone identifiers.
|
|
64
|
+
- Pin canonical base64 padding: byte sequences with nonzero padding bits reject under the shared decoding rule.
|
|
65
|
+
- Preserve immutable parsed bytes, snapshot caller-built signature parameters, and require branded messages for bases and related requests.
|
|
66
|
+
- Align validation precedence and negative zero serialization; support exact bigint decimal coefficients below 10³⁰ with RFC decimal magnitude limits.
|
|
67
|
+
- Add bounded RFC 8941/RFC 9651 Structured Fields parsing, ordered typed trees, unique mode, explicit schemas, and canonical serialization.
|
|
68
|
+
- Add lossless HTTP message, field, body, and transport values with copied bytes, target-form validation, and optional Content-Digest generation.
|
|
69
|
+
- Add all RFC 9421 signature-base components, related requests, trailers, Structured Fields selection, and exact query encoding.
|
|
70
|
+
- Register four wire corpus surfaces and two upstream batch formats; add checksummed HTTPWG, RFC 9421, and real HTTP capture tests.
|
|
71
|
+
- Keep the tooling smoke corpus independently pinned and excluded from the package.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all other
|
|
162
|
+
commercial damages or losses), even if such Contributor has been
|
|
163
|
+
advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
Copyright 2026 BaseLabs
|
|
179
|
+
|
|
180
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
|
+
you may not use this file except in compliance with the License.
|
|
182
|
+
You may obtain a copy of the License at
|
|
183
|
+
|
|
184
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
185
|
+
|
|
186
|
+
Unless required by applicable law or agreed to in writing, software
|
|
187
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
188
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
189
|
+
See the License for the specific language governing permissions and
|
|
190
|
+
limitations under the License.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
RequestSeal (TypeScript)
|
|
2
|
+
Copyright 2026 BaseLabs
|
|
3
|
+
|
|
4
|
+
This product includes software developed by BaseLabs
|
|
5
|
+
(https://github.com/baselabs).
|
|
6
|
+
|
|
7
|
+
The error vocabulary corresponds to the Elixir RequestSeal reference
|
|
8
|
+
(https://github.com/baselabs/request_seal) at v0.4.0 (commit b239287).
|
|
9
|
+
No Elixir runtime is included or required.
|
package/README.md
CHANGED
|
@@ -1,3 +1,165 @@
|
|
|
1
|
-
|
|
1
|
+
**Status:** development · **Kind:** overview · **Updated:** October 10, 2026 · **Governed by:** the public API and shared conformance corpus · **Review when:** package scope or installation changes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# RequestSeal
|
|
4
|
+
|
|
5
|
+
RequestSeal will provide standards-based HTTP message signatures and JOSE for TypeScript applications using WebCrypto. The first npm release is pending.
|
|
6
|
+
|
|
7
|
+
After publication:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @request-seal/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For development, use Node 22.12.0 or newer:
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm ci --ignore-scripts
|
|
17
|
+
npm run check
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The current package contains results, bounded errors, byte codecs, ordered JSON, numeric guards, deadline contexts, option snapshots, Structured Fields, lossless HTTP messages, RFC 9421 signature-base construction, cryptographic verification, public key formats, caller-owned local custody, HTTP signing and verification, explicit policies, content digests, quorum verification and Accept-Signature negotiation, compact JWS/JWE with one-level nesting, discovery snapshots and caches, and an explicit HTTPS discovery transport through `@request-seal/core/discovery-node`. See [multiple signatures](docs/reference/quorum.md), [JOSE APIs](docs/reference/jose.md), [signing and verification](docs/reference/sign-and-verify.md), [wire APIs](docs/reference/wire.md), [discovery](docs/reference/discovery.md), [error parity](docs/reference/error-parity.md), and [corpus format](docs/reference/corpus-format.md).
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Custody, Crypto } from "@request-seal/core";
|
|
24
|
+
|
|
25
|
+
// Generate example material; applications supply their own private PEM.
|
|
26
|
+
const pair = await crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]);
|
|
27
|
+
const der = new Uint8Array(await crypto.subtle.exportKey("pkcs8", pair.privateKey));
|
|
28
|
+
const privatePem = "-----BEGIN PRIVATE KEY-----\n" +
|
|
29
|
+
btoa(Array.from(der, b => String.fromCharCode(b)).join("")) +
|
|
30
|
+
"\n-----END PRIVATE KEY-----";
|
|
31
|
+
der.fill(0);
|
|
32
|
+
const messageBytes = new TextEncoder().encode("RequestSeal example");
|
|
33
|
+
const imported = await Custody.local("ed25519", privatePem);
|
|
34
|
+
if (imported.ok) {
|
|
35
|
+
const handle = imported.value;
|
|
36
|
+
try {
|
|
37
|
+
const signature = await Crypto.sign("ed25519", handle, messageBytes);
|
|
38
|
+
if (signature.ok) {
|
|
39
|
+
const verified = await Crypto.verify("ed25519", handle, signature.value, messageBytes);
|
|
40
|
+
console.log(verified.ok);
|
|
41
|
+
}
|
|
42
|
+
} finally {
|
|
43
|
+
await handle.release();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
HTTP tokens and JWS selectors are separate: use `{jws: "EdDSA"}` explicitly for
|
|
49
|
+
a JWS-bound handle. Handle methods accept a `withDeadline()` context.
|
|
50
|
+
`PublicKey.import()` accepts public JWK, PEM, or SPKI DER; public exports preserve
|
|
51
|
+
metadata restrictions and thumbprints follow RFC 7638. HMAC identities are optional
|
|
52
|
+
caller-supplied nonsecret values, never hashes of secrets. RSA-OAEP handles unwrap
|
|
53
|
+
into an AES operation capability; they return neither key bytes nor CryptoKey
|
|
54
|
+
references. See the [custody threat model](docs/design/threat-model.md).
|
|
55
|
+
|
|
56
|
+
## HTTP signing, verification, and digests
|
|
57
|
+
|
|
58
|
+
Use `sign()` and `verify()` with explicit `Policy` values, caller-owned key
|
|
59
|
+
resolvers, and replay storage. `Digest` handles RFC 9530 content digests;
|
|
60
|
+
`DigestState` supports incremental hashing. See [signing and verification](docs/reference/sign-and-verify.md).
|
|
61
|
+
|
|
62
|
+
## Web Bot Auth
|
|
63
|
+
|
|
64
|
+
Verify a protocol-00 request with a caller-trusted, fresh directory `keySet`
|
|
65
|
+
and captured branded `message`. The application supplies `now` in Unix seconds.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { WebBotAuth, ok, type AgentRequest } from "@request-seal/core";
|
|
69
|
+
|
|
70
|
+
const policy = WebBotAuth.Policy.create({
|
|
71
|
+
algorithms: ["ed25519"],
|
|
72
|
+
agents: ({ location }: AgentRequest) => ok(location === keySet.origin ? keySet : null),
|
|
73
|
+
cache: null,
|
|
74
|
+
freshness: { clock: () => now, maxAge: 60, skew: 5 },
|
|
75
|
+
content: "not_required",
|
|
76
|
+
replay: "not_required",
|
|
77
|
+
});
|
|
78
|
+
if (!policy.ok) throw new Error(policy.error.reason);
|
|
79
|
+
const authenticated = await WebBotAuth.verify(message, policy.value);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Supply your own signed directory snapshot or explicitly configured discovery
|
|
83
|
+
cache. Add required replay storage for nonce uniqueness. See
|
|
84
|
+
[Web Bot Auth](docs/reference/web-bot-auth.md) for signing, trust, held keys,
|
|
85
|
+
nested signatures, result facts, and replay commitments.
|
|
86
|
+
|
|
87
|
+
## JOSE
|
|
88
|
+
|
|
89
|
+
Use `JWS` for compact signing and verification, `JWE` for encryption and
|
|
90
|
+
authenticated decryption, and `Nested` for one-level nesting. Supply explicit
|
|
91
|
+
algorithm policies and caller-owned custody or `KeyManagement` capabilities.
|
|
92
|
+
See [JOSE APIs](docs/reference/jose.md).
|
|
93
|
+
|
|
94
|
+
## HTTP adapters and SSH custody
|
|
95
|
+
|
|
96
|
+
Use `@request-seal/core/node-http` for Node ingress and clients, `@request-seal/core/fetch`
|
|
97
|
+
for Fetch signing and proven Deno verification, and
|
|
98
|
+
`@request-seal/core/custody-ssh-agent` for caller-selected OpenSSH custody.
|
|
99
|
+
See [adapter contracts and framework recipes](docs/reference/adapters.md).
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import {captureRequest, verifyRequest} from "@request-seal/core/node-http";
|
|
103
|
+
|
|
104
|
+
async function authenticate(req, policy) {
|
|
105
|
+
const captured = await captureRequest(req); // Before body parsers.
|
|
106
|
+
if (!captured.ok) return captured;
|
|
107
|
+
const verified = await verifyRequest(req, policy, {label: "sig"});
|
|
108
|
+
if (!verified.ok) return verified;
|
|
109
|
+
// Feed the parser these authenticated bytes; the original stream is consumed.
|
|
110
|
+
req.body = JSON.parse(new TextDecoder("utf-8", {fatal: true}).decode(verified.value.bytes));
|
|
111
|
+
return verified;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For Web Bot Auth, supply a branded `WebBotAuth.Policy` with caller-configured
|
|
116
|
+
agent trust and discovery. The result is also available through `verification(req)`:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import {captureRequest, verifyWebBotAuth} from "@request-seal/core/node-http";
|
|
120
|
+
|
|
121
|
+
async function authenticateBot(req, policy) {
|
|
122
|
+
const captured = await captureRequest(req); // Before body parsers.
|
|
123
|
+
if (!captured.ok) return captured;
|
|
124
|
+
return verifyWebBotAuth(req, policy, {timeoutMs: 5000});
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import {signedFetch} from "@request-seal/core/fetch";
|
|
130
|
+
|
|
131
|
+
async function send(url, spec, signer) {
|
|
132
|
+
return signedFetch(url, {method: "POST", body: "hello"}, {spec, signer});
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
import {createSshAgent} from "@request-seal/core/custody-ssh-agent";
|
|
138
|
+
|
|
139
|
+
async function bindAgent(socketPath, publicKey) {
|
|
140
|
+
return createSshAgent("ed25519", socketPath, publicKey);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The caller supplies the socket and branded public key and owns agent startup
|
|
145
|
+
and key loading. Every returned signature is verified locally.
|
|
146
|
+
|
|
147
|
+
Fetch verification returns `invalid_request` outside the tested Deno 2.5.6
|
|
148
|
+
allowlist. Exact-target, cookie, and per-occurrence byte coverage remain refused.
|
|
149
|
+
|
|
150
|
+
## Compatibility
|
|
151
|
+
|
|
152
|
+
Compatibility is checked against the byte-preserved RequestSeal `v0.4.0` corpus. See [the corpus pin and update command](CONTRIBUTING.md). Development reports pending surfaces; releases require complete coverage.
|
|
153
|
+
|
|
154
|
+
Node 22.12.0 and 24.21.0 and Deno 2.5.6 verify the pinned published vectors.
|
|
155
|
+
Bun 1.3.14 WebCrypto rejects two valid Wycheproof ECDSA P-256 signatures:
|
|
156
|
+
items 261 (`s = 2^128`) and 262 (`s = n - 2^128`). The consumer policy in
|
|
157
|
+
[`tools/conformance/runtime-limits.json`](tools/conformance/runtime-limits.json)
|
|
158
|
+
applies only to that exact version and reports both as `runtime_limited`.
|
|
159
|
+
Published corpus verdicts stay valid. A stale entry, different rejection, unlisted
|
|
160
|
+
divergence, or divergence on another Bun version fails conformance. See the
|
|
161
|
+
[consumer runtime limitation contract](docs/reference/corpus-format.md#consumer-runtime-limitations)
|
|
162
|
+
and [test API compatibility](CONTRIBUTING.md#runtime-test-compatibility).
|
|
163
|
+
|
|
164
|
+
See [replay protection](docs/reference/replay.md) for the memory store and the
|
|
165
|
+
optional `@request-seal/core/replay-postgres` query adapter.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type InnerList } from "./structured-fields/index.ts";
|
|
2
|
+
import { type Message as HttpMessage } from "./message/index.ts";
|
|
3
|
+
import { type Result } from "./result.ts";
|
|
4
|
+
export type SignatureRequest = Readonly<{
|
|
5
|
+
label: string;
|
|
6
|
+
components: InnerList;
|
|
7
|
+
parameters: Readonly<Record<string, string | true>>;
|
|
8
|
+
}>;
|
|
9
|
+
export type AcceptSignature = readonly SignatureRequest[];
|
|
10
|
+
export declare function isAcceptSignature(v: unknown): v is AcceptSignature;
|
|
11
|
+
export declare function applicable(requests: AcceptSignature, target: "request" | "response"): Result<AcceptSignature>;
|
|
12
|
+
export declare function parseAcceptSignature(wire: unknown, options: unknown): Result<AcceptSignature>;
|
|
13
|
+
export declare function serializeAcceptSignature(requests: unknown): Result<Uint8Array>;
|
|
14
|
+
export type SignatureChoice = Readonly<{
|
|
15
|
+
algorithm: string;
|
|
16
|
+
created: number | null;
|
|
17
|
+
expires: number | null;
|
|
18
|
+
}>;
|
|
19
|
+
export type SignatureChooser = (request: SignatureRequest) => Result<SignatureChoice> | Promise<Result<SignatureChoice>>;
|
|
20
|
+
/** Fulfill atomically through caller-owned selection and the single-signature API. */
|
|
21
|
+
export declare function fulfillAcceptSignature(message: unknown, requests: unknown, chooser: unknown, signer: unknown, options?: unknown): Promise<Result<HttpMessage>>;
|
|
22
|
+
export declare const AcceptSignature: Readonly<{
|
|
23
|
+
parse: typeof parseAcceptSignature;
|
|
24
|
+
serialize: typeof serializeAcceptSignature;
|
|
25
|
+
fulfill: typeof fulfillAcceptSignature;
|
|
26
|
+
}>;
|