@request-seal/core 0.1.0 → 0.2.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 +15 -0
- package/README.md +341 -114
- package/dist/accept-signature.d.ts +11 -0
- package/dist/accept-signature.js +7 -0
- package/dist/adapters/fetch/index.d.ts +10 -0
- package/dist/adapters/fetch/index.js +21 -4
- package/dist/adapters/fetch/runtime.d.ts +1 -0
- package/dist/adapters/fetch/runtime.js +1 -0
- package/dist/adapters/node-http/index.d.ts +16 -0
- package/dist/adapters/node-http/index.js +8 -4
- package/dist/brand.d.ts +5 -0
- package/dist/brand.js +12 -0
- package/dist/bytes.d.ts +4 -0
- package/dist/bytes.js +5 -0
- package/dist/constants.d.ts +61 -1
- package/dist/constants.js +61 -1
- package/dist/context.d.ts +4 -0
- package/dist/context.js +3 -0
- package/dist/crypto/algorithm.d.ts +5 -0
- package/dist/crypto/index.d.ts +12 -2
- package/dist/crypto/index.js +34 -11
- package/dist/crypto/options.d.ts +3 -0
- package/dist/crypto/options.js +15 -0
- package/dist/crypto/primitive.d.ts +7 -3
- package/dist/crypto/primitive.js +36 -10
- package/dist/custody/content_key.d.ts +4 -0
- package/dist/custody/content_key.js +4 -2
- package/dist/custody/index.d.ts +2 -0
- package/dist/custody/index.js +5 -1
- package/dist/custody/local.d.ts +17 -1
- package/dist/custody/local.js +10 -5
- package/dist/custody/ssh-agent/index.d.ts +2 -0
- package/dist/custody/ssh-agent/index.js +11 -181
- package/dist/custody/ssh-agent/port.d.ts +19 -0
- package/dist/custody/ssh-agent/port.js +183 -0
- package/dist/digest.d.ts +22 -0
- package/dist/digest.js +15 -0
- package/dist/discovery/body.d.ts +7 -0
- package/dist/discovery/body.js +3 -0
- package/dist/discovery/cache.d.ts +9 -0
- package/dist/discovery/cache.js +2 -0
- package/dist/discovery/headers.d.ts +1 -0
- package/dist/discovery/index.d.ts +5 -0
- package/dist/discovery/index.js +10 -2
- package/dist/discovery/node-connection.d.ts +1 -1
- package/dist/discovery/node-connection.js +2 -2
- package/dist/discovery/node-trust.d.ts +2 -0
- package/dist/discovery/node-trust.js +9 -0
- package/dist/discovery/node.d.ts +4 -0
- package/dist/discovery/node.js +29 -11
- package/dist/discovery/source.d.ts +7 -0
- package/dist/discovery/source.js +5 -0
- package/dist/discovery/support.js +2 -3
- package/dist/errors/parity.d.ts +16 -1
- package/dist/errors/parity.js +14 -2
- package/dist/errors/types.d.ts +13 -1
- package/dist/errors/types.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/jose/header.d.ts +1 -0
- package/dist/jose/jwe.d.ts +9 -0
- package/dist/jose/jwe.js +17 -3
- package/dist/jose/jws.d.ts +11 -0
- package/dist/jose/jws.js +14 -2
- package/dist/jose/key-management.d.ts +11 -0
- package/dist/jose/key-management.js +13 -2
- package/dist/jose/nested.d.ts +6 -0
- package/dist/jose/nested.js +9 -1
- package/dist/json.d.ts +7 -0
- package/dist/key_handle.d.ts +12 -3
- package/dist/key_handle.js +32 -25
- package/dist/key_identity.d.ts +7 -0
- package/dist/key_identity.js +10 -2
- package/dist/message/index.d.ts +24 -0
- package/dist/message/index.js +20 -0
- package/dist/numbers.d.ts +6 -0
- package/dist/numbers.js +5 -0
- package/dist/policy.d.ts +15 -0
- package/dist/policy.js +30 -21
- package/dist/profile.d.ts +36 -0
- package/dist/profile.js +215 -0
- package/dist/public_key.d.ts +11 -2
- package/dist/public_key.js +31 -8
- package/dist/quorum/verification.d.ts +2 -0
- package/dist/quorum/verification.js +1 -0
- package/dist/quorum.d.ts +9 -0
- package/dist/quorum.js +7 -1
- package/dist/replay/claim.d.ts +5 -0
- package/dist/replay/claim.js +9 -1
- package/dist/replay/index.d.ts +6 -0
- package/dist/replay/index.js +13 -1
- package/dist/replay/postgres.d.ts +1 -0
- package/dist/replay/postgres.js +1 -0
- package/dist/replay/receipt.d.ts +1 -0
- package/dist/replay/receipt.js +1 -0
- package/dist/replay/store.d.ts +1 -0
- package/dist/replay/store.js +1 -0
- package/dist/replay-port.d.ts +6 -1
- package/dist/result.d.ts +3 -0
- package/dist/result.js +2 -0
- package/dist/sign.d.ts +5 -0
- package/dist/sign.js +1 -0
- package/dist/signature-base/index.d.ts +2 -0
- package/dist/signature-base/index.js +5 -1
- package/dist/structured-fields/index.d.ts +21 -0
- package/dist/structured-fields/index.js +14 -1
- package/dist/verification.d.ts +5 -1
- package/dist/verification.js +9 -6
- package/dist/verify-quorum.d.ts +1 -0
- package/dist/verify-quorum.js +1 -0
- package/dist/verify.d.ts +5 -0
- package/dist/verify.js +16 -11
- package/dist/web-bot-auth/index.d.ts +3 -0
- package/dist/web-bot-auth/index.js +3 -0
- package/dist/web-bot-auth/policy.d.ts +8 -0
- package/dist/web-bot-auth/policy.js +8 -4
- package/dist/web-bot-auth/verification.d.ts +8 -0
- package/dist/web-bot-auth/verification.js +4 -2
- package/package.json +17 -6
|
@@ -2,6 +2,7 @@ import { type Result } from "../result.ts";
|
|
|
2
2
|
import { type Verification } from "../verification.ts";
|
|
3
3
|
import type { QuorumMode, QuorumUnit, QuorumBinding } from "../quorum.ts";
|
|
4
4
|
import type { Layer, Reason } from "../errors/parity.ts";
|
|
5
|
+
/** Branded per-slot verification and quorum evaluation facts. */
|
|
5
6
|
export type QuorumVerification = Readonly<{
|
|
6
7
|
profile: Readonly<{
|
|
7
8
|
name: "rfc9421";
|
|
@@ -31,6 +32,7 @@ export type QuorumVerification = Readonly<{
|
|
|
31
32
|
principal: "unattributed";
|
|
32
33
|
authorization: "not_evaluated";
|
|
33
34
|
}>;
|
|
35
|
+
/** Check the private brand of a quorum verification result. */
|
|
34
36
|
export declare function isQuorumVerification(v: unknown): v is QuorumVerification;
|
|
35
37
|
export declare function completeQuorum(value: QuorumVerification): Result<QuorumVerification>;
|
|
36
38
|
export declare function quorumFacts(value: unknown): Result<unknown>;
|
|
@@ -2,6 +2,7 @@ import { ok, err } from "../result.js";
|
|
|
2
2
|
import { coreError } from "../errors/types.js";
|
|
3
3
|
import { verificationFacts } from "../verification.js";
|
|
4
4
|
const results = new WeakSet();
|
|
5
|
+
/** Check the private brand of a quorum verification result. */
|
|
5
6
|
export function isQuorumVerification(v) {
|
|
6
7
|
return typeof v === "object" && v !== null && results.has(v);
|
|
7
8
|
}
|
package/dist/quorum.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { type Policy } from "./policy.ts";
|
|
2
2
|
import { type Result } from "./result.ts";
|
|
3
|
+
/** Require all, any, or a threshold number of successful signers. */
|
|
3
4
|
export type QuorumMode = "all" | "any" | Readonly<{
|
|
4
5
|
threshold: number;
|
|
5
6
|
}>;
|
|
7
|
+
/** Count quorum satisfaction by keys, principals, or roles. */
|
|
6
8
|
export type QuorumUnit = "keys" | "principals" | "roles";
|
|
9
|
+
/** A named quorum slot with a policy and optional signature and principal selectors. */
|
|
7
10
|
export type SignerSlot = Readonly<{
|
|
8
11
|
id: string;
|
|
9
12
|
policy: Policy;
|
|
@@ -13,6 +16,7 @@ export type SignerSlot = Readonly<{
|
|
|
13
16
|
principal: string | null;
|
|
14
17
|
role: string | null;
|
|
15
18
|
}>;
|
|
19
|
+
/** A same-component or same-parameter constraint across quorum slots. */
|
|
16
20
|
export type QuorumBinding = Readonly<{
|
|
17
21
|
kind: "nested";
|
|
18
22
|
outer: string;
|
|
@@ -22,6 +26,7 @@ export type QuorumBinding = Readonly<{
|
|
|
22
26
|
name: "nonce" | "tag" | "created";
|
|
23
27
|
slots: readonly string[];
|
|
24
28
|
}>;
|
|
29
|
+
/** A branded policy for bounded multi-signature verification. */
|
|
25
30
|
export type Quorum = Readonly<{
|
|
26
31
|
mode: QuorumMode;
|
|
27
32
|
unit: QuorumUnit;
|
|
@@ -32,8 +37,12 @@ export type Quorum = Readonly<{
|
|
|
32
37
|
bindings: readonly QuorumBinding[];
|
|
33
38
|
maxSignatures: number;
|
|
34
39
|
}>;
|
|
40
|
+
/** Check the private brand of a quorum policy. */
|
|
35
41
|
export declare function isQuorum(v: unknown): v is Quorum;
|
|
42
|
+
/** Snapshot, validate, and brand a quorum policy. */
|
|
36
43
|
export declare function createQuorum(input: unknown): Result<Quorum>;
|
|
44
|
+
/** Quorum policy construction. */
|
|
37
45
|
export declare const Quorum: Readonly<{
|
|
46
|
+
/** Snapshot, validate, and brand a bounded quorum policy. */
|
|
38
47
|
create: typeof createQuorum;
|
|
39
48
|
}>;
|
package/dist/quorum.js
CHANGED
|
@@ -8,6 +8,7 @@ const quorums = new WeakSet();
|
|
|
8
8
|
const text = (v) => typeof v === "string" &&
|
|
9
9
|
encodeUtf8(v).length >= 1 &&
|
|
10
10
|
encodeUtf8(v).length <= 256;
|
|
11
|
+
/** Check the private brand of a quorum policy. */
|
|
11
12
|
export function isQuorum(v) {
|
|
12
13
|
return typeof v === "object" && v !== null && quorums.has(v);
|
|
13
14
|
}
|
|
@@ -16,6 +17,7 @@ function snapshot(v, keys) {
|
|
|
16
17
|
ensure(r.ok, "invalid_quorum", "input");
|
|
17
18
|
return r.value;
|
|
18
19
|
}
|
|
20
|
+
/** Snapshot, validate, and brand a quorum policy. */
|
|
19
21
|
export function createQuorum(input) {
|
|
20
22
|
try {
|
|
21
23
|
const a = snapshot(input, [
|
|
@@ -142,4 +144,8 @@ export function createQuorum(input) {
|
|
|
142
144
|
return err(bounded(e, "invalid_quorum", "input"));
|
|
143
145
|
}
|
|
144
146
|
}
|
|
145
|
-
|
|
147
|
+
/** Quorum policy construction. */
|
|
148
|
+
export const Quorum = Object.freeze({
|
|
149
|
+
/** Snapshot, validate, and brand a bounded quorum policy. */
|
|
150
|
+
create: createQuorum
|
|
151
|
+
});
|
package/dist/replay/claim.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export declare function validSeconds(value: unknown): value is number;
|
|
|
4
4
|
/** Exact signed-64-bit lower bound; bigint preserves ends outside safe numbers. */
|
|
5
5
|
export declare function validRetention(value: unknown): value is number | bigint;
|
|
6
6
|
export declare function boundedReplayBytes(v: unknown): v is Uint8Array;
|
|
7
|
+
/** Check the private brand of an atomic replay claim. */
|
|
7
8
|
export declare function isReplayClaim(value: unknown): value is ReplayClaim;
|
|
9
|
+
/** Copy, validate, and brand a replay claim. */
|
|
8
10
|
export declare function createClaim(input: unknown): Result<ReplayClaim>;
|
|
9
11
|
/** Exclusive expiration, inclusive max age. Authenticate the window before deriving retention. */
|
|
10
12
|
export declare function retentionEnd(input: unknown): Result<number>;
|
|
@@ -13,7 +15,10 @@ export declare function retainUntil(input: unknown): Result<number>;
|
|
|
13
15
|
/** Injective byte encoding, also suitable for PostgreSQL decode($n,'hex'). */
|
|
14
16
|
export declare function hex(bytes: Uint8Array): string;
|
|
15
17
|
export declare function claimRow(input: unknown): Result<readonly [string, string, string]>;
|
|
18
|
+
/** Replay-claim construction and private-brand validation. */
|
|
16
19
|
export declare const Claim: Readonly<{
|
|
20
|
+
/** Copy, validate, and brand an atomic replay claim. */
|
|
17
21
|
create: typeof createClaim;
|
|
22
|
+
/** Check the private brand of a replay claim. */
|
|
18
23
|
valid: typeof isReplayClaim;
|
|
19
24
|
}>;
|
package/dist/replay/claim.js
CHANGED
|
@@ -22,9 +22,11 @@ export function boundedReplayBytes(v) {
|
|
|
22
22
|
return length >= 1 && length <= KEY_IDENTITY_MAX_BYTES;
|
|
23
23
|
}
|
|
24
24
|
;
|
|
25
|
+
/** Check the private brand of an atomic replay claim. */
|
|
25
26
|
export function isReplayClaim(value) {
|
|
26
27
|
return typeof value === 'object' && value !== null && claims.has(value);
|
|
27
28
|
}
|
|
29
|
+
/** Copy, validate, and brand a replay claim. */
|
|
28
30
|
export function createClaim(input) {
|
|
29
31
|
try {
|
|
30
32
|
const r = snapshotOptions(input, ['namespace', 'key', 'retainUntil']);
|
|
@@ -68,4 +70,10 @@ export function claimRow(input) {
|
|
|
68
70
|
return err(replayError('invalid_claim'));
|
|
69
71
|
return ok(Object.freeze([hex(input.namespace), hex(input.key), input.retainUntil.toString()]));
|
|
70
72
|
}
|
|
71
|
-
|
|
73
|
+
/** Replay-claim construction and private-brand validation. */
|
|
74
|
+
export const Claim = Object.freeze({
|
|
75
|
+
/** Copy, validate, and brand an atomic replay claim. */
|
|
76
|
+
create: createClaim,
|
|
77
|
+
/** Check the private brand of a replay claim. */
|
|
78
|
+
valid: isReplayClaim
|
|
79
|
+
});
|
package/dist/replay/index.d.ts
CHANGED
|
@@ -3,10 +3,16 @@ import { retainUntil, claimRow } from './claim.ts';
|
|
|
3
3
|
export { Claim, createClaim, isReplayClaim } from './claim.ts';
|
|
4
4
|
export { isReplayReceipt } from './receipt.ts';
|
|
5
5
|
export { createReplayStore, isReplayStore } from './store.ts';
|
|
6
|
+
/** Atomic claim, expiration sweep, and retention helper operations. */
|
|
6
7
|
export declare const Replay: Readonly<{
|
|
8
|
+
/** Atomically reserve the claim or report that it was already claimed. */
|
|
7
9
|
claim: typeof claim;
|
|
10
|
+
/** Remove expired replay claims and return the removal count. */
|
|
8
11
|
sweep: typeof sweep;
|
|
12
|
+
/** Compute the retention deadline from validated freshness facts. */
|
|
9
13
|
retainUntil: typeof retainUntil;
|
|
14
|
+
/** Encode a branded claim as namespace, key, and retention database values. */
|
|
10
15
|
row: typeof claimRow;
|
|
16
|
+
/** Validate and brand a caller-owned atomic replay store. */
|
|
11
17
|
store: typeof createReplayStore;
|
|
12
18
|
}>;
|
package/dist/replay/index.js
CHANGED
|
@@ -3,4 +3,16 @@ import { retainUntil, claimRow } from './claim.js';
|
|
|
3
3
|
export { Claim, createClaim, isReplayClaim } from './claim.js';
|
|
4
4
|
export { isReplayReceipt } from './receipt.js';
|
|
5
5
|
export { createReplayStore, isReplayStore } from './store.js';
|
|
6
|
-
|
|
6
|
+
/** Atomic claim, expiration sweep, and retention helper operations. */
|
|
7
|
+
export const Replay = Object.freeze({
|
|
8
|
+
/** Atomically reserve the claim or report that it was already claimed. */
|
|
9
|
+
claim,
|
|
10
|
+
/** Remove expired replay claims and return the removal count. */
|
|
11
|
+
sweep,
|
|
12
|
+
/** Compute the retention deadline from validated freshness facts. */
|
|
13
|
+
retainUntil,
|
|
14
|
+
/** Encode a branded claim as namespace, key, and retention database values. */
|
|
15
|
+
row: claimRow,
|
|
16
|
+
/** Validate and brand a caller-owned atomic replay store. */
|
|
17
|
+
store: createReplayStore
|
|
18
|
+
});
|
|
@@ -5,6 +5,7 @@ export type Query = (sql: string, params: readonly string[], context: Readonly<{
|
|
|
5
5
|
signal: AbortSignal;
|
|
6
6
|
remainingMs: number;
|
|
7
7
|
}>) => Promise<number>;
|
|
8
|
+
/** Validate a table name and return replay-store creation SQL. */
|
|
8
9
|
export declare function ddl(table: unknown): Result<string>;
|
|
9
10
|
/** No database, pool, transaction, or timer starts here. Late commits remain indeterminate. */
|
|
10
11
|
export declare function createStore(options: unknown): Result<ReplayStore>;
|
package/dist/replay/postgres.js
CHANGED
|
@@ -5,6 +5,7 @@ import { ok, err } from '../result.js';
|
|
|
5
5
|
import { claimRow, isReplayClaim, validSeconds } from './claim.js';
|
|
6
6
|
import { createReplayStore, storeOperation } from './store.js';
|
|
7
7
|
const tableName = (value) => typeof value === 'string' && value.length >= 1 && value.length <= 63 && /^[a-z][a-z0-9_]*$/.test(value);
|
|
8
|
+
/** Validate a table name and return replay-store creation SQL. */
|
|
8
9
|
export function ddl(table) {
|
|
9
10
|
return tableName(table) ? ok(`CREATE TABLE "${table}" (namespace bytea NOT NULL, key bytea NOT NULL, retain_until bigint NOT NULL, PRIMARY KEY (namespace, key))`) : err(replayError('invalid_store'));
|
|
10
11
|
}
|
package/dist/replay/receipt.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Result } from '../result.ts';
|
|
2
2
|
import type { ReplayReceipt } from '../replay-port.ts';
|
|
3
|
+
/** Check the private brand of a successful replay receipt. */
|
|
3
4
|
export declare function isReplayReceipt(value: unknown): value is ReplayReceipt;
|
|
4
5
|
export declare function createReceipt(input: unknown): Result<ReplayReceipt>;
|
package/dist/replay/receipt.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ok, err } from '../result.js';
|
|
|
4
4
|
import { validRetention } from './claim.js';
|
|
5
5
|
// Verification produces safe-number ends; share the claim bounds for those ends.
|
|
6
6
|
const receipts = new WeakSet();
|
|
7
|
+
/** Check the private brand of a successful replay receipt. */
|
|
7
8
|
export function isReplayReceipt(value) {
|
|
8
9
|
return typeof value === 'object' && value !== null && receipts.has(value);
|
|
9
10
|
}
|
package/dist/replay/store.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Context } from '../context.ts';
|
|
2
2
|
import { type Result } from '../result.ts';
|
|
3
3
|
import type { ReplayStore } from '../replay-port.ts';
|
|
4
|
+
/** Check the private brand of a replay store. */
|
|
4
5
|
export declare function isReplayStore(value: unknown): value is ReplayStore;
|
|
5
6
|
/** Normalize caller ports once, binding own methods to the caller's receiver. */
|
|
6
7
|
export declare function createReplayStore(input: unknown): Result<ReplayStore>;
|
package/dist/replay/store.js
CHANGED
|
@@ -4,6 +4,7 @@ import { isRequestSealError, replayError } from '../errors/types.js';
|
|
|
4
4
|
import { ok, err } from '../result.js';
|
|
5
5
|
import { isReplayClaim, validSeconds } from './claim.js';
|
|
6
6
|
const stores = new WeakSet();
|
|
7
|
+
/** Check the private brand of a replay store. */
|
|
7
8
|
export function isReplayStore(value) {
|
|
8
9
|
return typeof value === 'object' && value !== null && stores.has(value);
|
|
9
10
|
}
|
package/dist/replay-port.d.ts
CHANGED
|
@@ -8,16 +8,21 @@ export type ReplayClaim = Readonly<{
|
|
|
8
8
|
}>;
|
|
9
9
|
/** Bounded callback vocabulary; normalized by Replay.claim and Replay.sweep. */
|
|
10
10
|
export type ReplayStoreFailure = "unavailable" | "timeout" | "full" | "failure";
|
|
11
|
+
/** A store result with branded errors or the bounded callback failure vocabulary. */
|
|
11
12
|
export type ReplayStoreResult<T> = Result<T> | Readonly<{
|
|
12
13
|
ok: false;
|
|
13
14
|
error: ReplayStoreFailure;
|
|
14
15
|
}>;
|
|
16
|
+
/** A caller-owned atomic claim and expiration-sweep port. */
|
|
15
17
|
export type ReplayStore = Readonly<{
|
|
16
18
|
/** Public adapter identity; unnamed caller implementations use "caller". */
|
|
17
19
|
identity?: string;
|
|
20
|
+
/** Atomically reserve the claim or report that it was already claimed. */
|
|
18
21
|
claim: (claim: ReplayClaim, context: Context) => ReplayStoreResult<"claimed" | "already_claimed"> | Promise<ReplayStoreResult<"claimed" | "already_claimed">>;
|
|
22
|
+
/** Remove expired replay claims and return the removal count. */
|
|
19
23
|
sweep: (now: number, context: Context) => ReplayStoreResult<number> | Promise<ReplayStoreResult<number>>;
|
|
20
24
|
}>;
|
|
25
|
+
/** Verified signature and profile facts supplied to a replay commitment callback. */
|
|
21
26
|
export type ReplayFacts = Readonly<{
|
|
22
27
|
identifier: string;
|
|
23
28
|
algorithm: import("./crypto/algorithm.ts").SigningAlgorithm;
|
|
@@ -27,7 +32,7 @@ export type ReplayFacts = Readonly<{
|
|
|
27
32
|
expires: number | null;
|
|
28
33
|
profile: Readonly<{
|
|
29
34
|
name: "rfc9421";
|
|
30
|
-
}
|
|
35
|
+
}> | import("./profile.ts").ProfileStamp;
|
|
31
36
|
}>;
|
|
32
37
|
/** Successful atomic claim; contains only public adapter identity and retention. */
|
|
33
38
|
export type ReplayReceipt = Readonly<{
|
package/dist/result.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type RequestSealError } from './errors/types.ts';
|
|
2
|
+
/** A success value or a branded, bounded error. */
|
|
2
3
|
export type Result<T> = {
|
|
3
4
|
readonly ok: true;
|
|
4
5
|
readonly value: T;
|
|
@@ -6,5 +7,7 @@ export type Result<T> = {
|
|
|
6
7
|
readonly ok: false;
|
|
7
8
|
readonly error: RequestSealError;
|
|
8
9
|
};
|
|
10
|
+
/** Freeze a successful result containing the supplied value. */
|
|
9
11
|
export declare const ok: <T>(value: T) => Result<T>;
|
|
12
|
+
/** Freeze a failed result after checking its error brand. */
|
|
10
13
|
export declare const err: <T = never>(error: RequestSealError) => Result<T>;
|
package/dist/result.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { isRequestSealError } from './errors/types.js';
|
|
2
|
+
/** Freeze a successful result containing the supplied value. */
|
|
2
3
|
export const ok = (value) => Object.freeze({ ok: true, value });
|
|
4
|
+
/** Freeze a failed result after checking its error brand. */
|
|
3
5
|
export const err = (error) => {
|
|
4
6
|
if (!isRequestSealError(error))
|
|
5
7
|
throw new TypeError('Unbranded Result error');
|
package/dist/sign.d.ts
CHANGED
|
@@ -3,12 +3,15 @@ import { type SigningAlgorithm } from "./crypto/algorithm.ts";
|
|
|
3
3
|
import { type Message as HttpMessage } from "./message/index.ts";
|
|
4
4
|
import { type InnerList } from "./structured-fields/index.ts";
|
|
5
5
|
import { type Result } from "./result.ts";
|
|
6
|
+
/** A caller-owned signing callback receiving the algorithm, base bytes, and context. */
|
|
6
7
|
export type Signer = (algorithm: SigningAlgorithm, base: Uint8Array, context: Context) => Result<Uint8Array> | Promise<Result<Uint8Array>>;
|
|
8
|
+
/** A label, signature-input value, and signing algorithm. */
|
|
7
9
|
export type SignatureSpec = Readonly<{
|
|
8
10
|
label: string;
|
|
9
11
|
signatureInput: string | Uint8Array | InnerList;
|
|
10
12
|
algorithm: SigningAlgorithm;
|
|
11
13
|
}>;
|
|
14
|
+
/** Explicit freshness, key identifier, nonce, and tag parameters for signing. */
|
|
12
15
|
export type SigningParameters = Readonly<{
|
|
13
16
|
created?: boolean;
|
|
14
17
|
expiresIn: number | null;
|
|
@@ -17,6 +20,7 @@ export type SigningParameters = Readonly<{
|
|
|
17
20
|
keyid?: string | null;
|
|
18
21
|
tag?: string | null;
|
|
19
22
|
}>;
|
|
23
|
+
/** Components, algorithm, and optional digest and freshness settings for signing. */
|
|
20
24
|
export type SigningSpec = Readonly<{
|
|
21
25
|
label: string;
|
|
22
26
|
components: string;
|
|
@@ -31,4 +35,5 @@ export type SigningSpec = Readonly<{
|
|
|
31
35
|
digest?: readonly string[] | null;
|
|
32
36
|
fieldSchemas?: unknown;
|
|
33
37
|
}>;
|
|
38
|
+
/** Sign a lossless HTTP message with explicit components and caller-owned custody. */
|
|
34
39
|
export declare function sign(message: unknown, spec: unknown, signer: unknown, options?: unknown): Promise<Result<HttpMessage>>;
|
package/dist/sign.js
CHANGED
|
@@ -36,6 +36,7 @@ function append(m, name, bytes) {
|
|
|
36
36
|
result(FieldOccurrence.create({ name, value: bytes, section: "headers" })),
|
|
37
37
|
]);
|
|
38
38
|
}
|
|
39
|
+
/** Sign a lossless HTTP message with explicit components and caller-owned custody. */
|
|
39
40
|
export async function sign(message, spec, signer, options = {}) {
|
|
40
41
|
try {
|
|
41
42
|
const s = take(spec, [
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type Result } from '../result.ts';
|
|
2
2
|
/** Ordered identifiers and parameters are serialized exactly once for each output line. */
|
|
3
3
|
export declare function build(input: unknown, parameters: unknown, options?: unknown): Result<Uint8Array>;
|
|
4
|
+
/** RFC 9421 signature-base construction operations. */
|
|
4
5
|
export declare const SignatureBase: Readonly<{
|
|
6
|
+
/** Build RFC 9421 signature-base bytes from a lossless message. */
|
|
5
7
|
build: typeof build;
|
|
6
8
|
}>;
|
|
@@ -317,4 +317,8 @@ export function build(input, parameters, options = {}) {
|
|
|
317
317
|
: signatureBaseError('invalid_signature_parameters'));
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
|
-
|
|
320
|
+
/** RFC 9421 signature-base construction operations. */
|
|
321
|
+
export const SignatureBase = Object.freeze({
|
|
322
|
+
/** Build RFC 9421 signature-base bytes from a lossless message. */
|
|
323
|
+
build
|
|
324
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { STRUCTURED_FIELDS_LIMITS as CEILINGS } from '../constants.ts';
|
|
2
2
|
import { type Result } from '../result.ts';
|
|
3
|
+
/** A typed Structured Fields bare value. */
|
|
3
4
|
export type Bare = Readonly<{
|
|
4
5
|
kind: 'integer' | 'date';
|
|
5
6
|
value: number;
|
|
@@ -21,29 +22,39 @@ export type Bare = Readonly<{
|
|
|
21
22
|
}>;
|
|
22
23
|
export declare function decimalSource(value: Bare): string | undefined;
|
|
23
24
|
export declare function copyDecimalSource(from: Bare, to: Bare): void;
|
|
25
|
+
/** Ordered Structured Fields parameter names and bare values. */
|
|
24
26
|
export type Parameters = readonly (readonly [string, Bare])[];
|
|
27
|
+
/** A Structured Fields item and its ordered parameters. */
|
|
25
28
|
export type Item = Readonly<{
|
|
26
29
|
kind: 'item';
|
|
27
30
|
value: Bare;
|
|
28
31
|
parameters: Parameters;
|
|
29
32
|
}>;
|
|
33
|
+
/** A Structured Fields inner list and its ordered parameters. */
|
|
30
34
|
export type InnerList = Readonly<{
|
|
31
35
|
kind: 'inner_list';
|
|
32
36
|
value: readonly Item[];
|
|
33
37
|
parameters: Parameters;
|
|
34
38
|
}>;
|
|
39
|
+
/** A Structured Fields item or inner list. */
|
|
35
40
|
export type Member = Item | InnerList;
|
|
41
|
+
/** An ordered Structured Fields list. */
|
|
36
42
|
export type List = Readonly<{
|
|
37
43
|
kind: 'list';
|
|
38
44
|
value: readonly Member[];
|
|
39
45
|
}>;
|
|
46
|
+
/** An ordered Structured Fields dictionary. */
|
|
40
47
|
export type Dictionary = Readonly<{
|
|
41
48
|
kind: 'dictionary';
|
|
42
49
|
value: readonly (readonly [string, Member])[];
|
|
43
50
|
}>;
|
|
51
|
+
/** A branded Structured Fields item, inner list, list, or dictionary. */
|
|
44
52
|
export type Value = Item | InnerList | List | Dictionary;
|
|
53
|
+
/** The supported Structured Fields root kinds. */
|
|
45
54
|
export type FieldType = 'item' | 'list' | 'dictionary';
|
|
55
|
+
/** The supported Structured Fields specification revisions. */
|
|
46
56
|
export type Revision = 'rfc8941' | 'rfc9651';
|
|
57
|
+
/** A branded field schema with revision, combination, and byte policies. */
|
|
47
58
|
export type Schema = Readonly<{
|
|
48
59
|
revision: Revision;
|
|
49
60
|
type: FieldType;
|
|
@@ -51,7 +62,9 @@ export type Schema = Readonly<{
|
|
|
51
62
|
parameterTypes: readonly Bare['kind'][];
|
|
52
63
|
innerLists: boolean;
|
|
53
64
|
}>;
|
|
65
|
+
/** Structured Fields parser ceilings. @inline */
|
|
54
66
|
export type Limits = typeof CEILINGS;
|
|
67
|
+
/** Parser limits, schema selection, and duplicate policies. */
|
|
55
68
|
export type Options = {
|
|
56
69
|
schema: Revision | Schema;
|
|
57
70
|
uniqueKeys?: 'all' | string[];
|
|
@@ -61,8 +74,11 @@ export type Options = {
|
|
|
61
74
|
-readonly [K in keyof Limits]: number;
|
|
62
75
|
}>;
|
|
63
76
|
};
|
|
77
|
+
/** Check the private brand of a Structured Fields value. */
|
|
64
78
|
export declare function isStructuredFieldsValue(value: unknown): value is Value;
|
|
79
|
+
/** Check the private brand of a Structured Fields schema. */
|
|
65
80
|
export declare function isStructuredFieldsSchema(value: unknown): value is Schema;
|
|
81
|
+
/** Validate and brand a Structured Fields schema. */
|
|
66
82
|
export declare function createSchema(input: unknown): Result<Schema>;
|
|
67
83
|
/** A single cursor, bounded container depth, and encounter counts before deduplication. */
|
|
68
84
|
export declare function parse(fieldType: FieldType | unknown, raw: unknown, options?: unknown): Result<Value>;
|
|
@@ -70,9 +86,14 @@ export declare function parse(fieldType: FieldType | unknown, raw: unknown, opti
|
|
|
70
86
|
export declare function serialize(value: unknown, options?: unknown): Result<Uint8Array>;
|
|
71
87
|
/** Select ordered occurrences, combine with comma-space, and parse under explicit policy. */
|
|
72
88
|
export declare function parseField(message: unknown, name: unknown, schema: Schema, section?: 'headers' | 'trailers', options?: unknown): Result<Value>;
|
|
89
|
+
/** Bounded parsing, serialization, and field-schema construction. */
|
|
73
90
|
export declare const StructuredFields: Readonly<{
|
|
91
|
+
/** Parse and validate the supported wire representation. */
|
|
74
92
|
parse: typeof parse;
|
|
93
|
+
/** Combine field occurrences according to a branded schema and parse them. */
|
|
75
94
|
parseField: typeof parseField;
|
|
95
|
+
/** Serialize validated values to their canonical wire representation. */
|
|
76
96
|
serialize: typeof serialize;
|
|
97
|
+
/** Validate and brand a Structured Fields schema. */
|
|
77
98
|
createSchema: typeof createSchema;
|
|
78
99
|
}>;
|
|
@@ -26,9 +26,11 @@ const allTypes = [...baseTypes, 'date', 'display_string'];
|
|
|
26
26
|
const schemas = new WeakMap();
|
|
27
27
|
const values = new WeakSet();
|
|
28
28
|
const schemaValues = new WeakSet();
|
|
29
|
+
/** Check the private brand of a Structured Fields value. */
|
|
29
30
|
export function isStructuredFieldsValue(value) {
|
|
30
31
|
return typeof value === 'object' && value !== null && values.has(value);
|
|
31
32
|
}
|
|
33
|
+
/** Check the private brand of a Structured Fields schema. */
|
|
32
34
|
export function isStructuredFieldsSchema(value) {
|
|
33
35
|
return typeof value === 'object' && value !== null && schemaValues.has(value);
|
|
34
36
|
}
|
|
@@ -39,6 +41,7 @@ function ensure(value, reason) {
|
|
|
39
41
|
if (!value)
|
|
40
42
|
fail(reason);
|
|
41
43
|
}
|
|
44
|
+
/** Validate and brand a Structured Fields schema. */
|
|
42
45
|
export function createSchema(input) {
|
|
43
46
|
try {
|
|
44
47
|
const s = snapshotOptions(input, [
|
|
@@ -655,4 +658,14 @@ export function parseField(message, name, schema, section = 'headers', options =
|
|
|
655
658
|
return err(error(e, 'invalid_message'));
|
|
656
659
|
}
|
|
657
660
|
}
|
|
658
|
-
|
|
661
|
+
/** Bounded parsing, serialization, and field-schema construction. */
|
|
662
|
+
export const StructuredFields = Object.freeze({
|
|
663
|
+
/** Parse and validate the supported wire representation. */
|
|
664
|
+
parse,
|
|
665
|
+
/** Combine field occurrences according to a branded schema and parse them. */
|
|
666
|
+
parseField,
|
|
667
|
+
/** Serialize validated values to their canonical wire representation. */
|
|
668
|
+
serialize,
|
|
669
|
+
/** Validate and brand a Structured Fields schema. */
|
|
670
|
+
createSchema
|
|
671
|
+
});
|
package/dist/verification.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Parameters } from "./structured-fields/index.ts";
|
|
2
2
|
import type { DigestFacts } from "./digest.ts";
|
|
3
3
|
import { type Result } from "./result.ts";
|
|
4
|
+
/** The clock, age, skew, and timestamps used in successful freshness validation. */
|
|
4
5
|
export type FreshnessFacts = Readonly<{
|
|
5
6
|
now: number;
|
|
6
7
|
created: number | null;
|
|
@@ -8,6 +9,7 @@ export type FreshnessFacts = Readonly<{
|
|
|
8
9
|
maxAge: number | null;
|
|
9
10
|
skew: number;
|
|
10
11
|
}>;
|
|
12
|
+
/** Branded signature, content, freshness, replay, and principal verification facts. */
|
|
11
13
|
export type Verification = Readonly<{
|
|
12
14
|
label: string;
|
|
13
15
|
signature: Readonly<{
|
|
@@ -19,15 +21,17 @@ export type Verification = Readonly<{
|
|
|
19
21
|
}>;
|
|
20
22
|
profile: Readonly<{
|
|
21
23
|
name: "rfc9421";
|
|
22
|
-
}> | import("./web-bot-auth/verification.ts").WebBotAuthProfile;
|
|
24
|
+
}> | import("./web-bot-auth/verification.ts").WebBotAuthProfile | import("./profile.ts").ProfileStamp;
|
|
23
25
|
content: "not_required" | DigestFacts;
|
|
24
26
|
freshness: "not_evaluated" | FreshnessFacts;
|
|
25
27
|
replay: "not_required" | import("./replay-port.ts").ReplayReceipt;
|
|
26
28
|
principal: "unattributed" | import("./web-bot-auth/verification.ts").AgentPrincipal | import("./web-bot-auth/verification.ts").HeldPrincipal;
|
|
27
29
|
authorization: "not_evaluated";
|
|
28
30
|
}>;
|
|
31
|
+
/** Check the private brand of a single-signature verification result. */
|
|
29
32
|
export declare function isVerification(value: unknown): value is Verification;
|
|
30
33
|
export declare function completed(value: Verification): Result<Verification>;
|
|
31
34
|
/** Ordered language-neutral facts; cryptographic material is never serialized. */
|
|
32
35
|
export declare function verificationFacts(value: unknown): Result<unknown>;
|
|
36
|
+
/** Encode the canonical public verification facts as JSON bytes. */
|
|
33
37
|
export declare function serializeVerification(value: unknown): Result<Uint8Array>;
|
package/dist/verification.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { isWebBotAuthVerification, webBotAuthFacts } from './web-bot-auth/verification.js';
|
|
2
2
|
import { isQuorumVerification, quorumFacts } from './quorum/verification.js';
|
|
3
|
-
import { deepFreeze } from "./brand.js";
|
|
4
|
-
import {
|
|
3
|
+
import { deepFreeze, inspection } from "./brand.js";
|
|
4
|
+
import { encodeUtf8 } from "./runtime.js";
|
|
5
5
|
import { decimalSource, copyDecimalSource } from "./structured-fields/index.js";
|
|
6
6
|
import { isReplayReceipt } from "./replay/receipt.js";
|
|
7
7
|
import { coreError } from "./errors/types.js";
|
|
8
8
|
import { ok, err } from "./result.js";
|
|
9
9
|
const verifications = new WeakSet();
|
|
10
|
+
/** Check the private brand of a single-signature verification result. */
|
|
10
11
|
export function isVerification(value) {
|
|
11
12
|
return (typeof value === "object" && value !== null && verifications.has(value));
|
|
12
13
|
}
|
|
@@ -60,8 +61,7 @@ export function completed(value) {
|
|
|
60
61
|
});
|
|
61
62
|
Object.defineProperties(result, {
|
|
62
63
|
toJSON: { value: inspect },
|
|
63
|
-
|
|
64
|
-
[Symbol.for("Deno.customInspect")]: { value: inspect },
|
|
64
|
+
...inspection(inspect),
|
|
65
65
|
});
|
|
66
66
|
Object.freeze(result);
|
|
67
67
|
verifications.add(result);
|
|
@@ -124,7 +124,9 @@ export function verificationFacts(value) {
|
|
|
124
124
|
keyid: value.signature.keyid,
|
|
125
125
|
crypto: "valid",
|
|
126
126
|
},
|
|
127
|
-
profile: value.profile
|
|
127
|
+
profile: Array.isArray(value.profile.name)
|
|
128
|
+
? Object.fromEntries(Object.entries(value.profile).map(([k, v]) => [k, typeof v === "boolean" ? String(v) : v === null ? "" : v]))
|
|
129
|
+
: value.profile,
|
|
128
130
|
content: value.content === "not_required"
|
|
129
131
|
? "not_required"
|
|
130
132
|
: { ...value.content, bytes: number(value.content.bytes) },
|
|
@@ -134,6 +136,7 @@ export function verificationFacts(value) {
|
|
|
134
136
|
authorization: value.authorization,
|
|
135
137
|
});
|
|
136
138
|
}
|
|
139
|
+
/** Encode the canonical public verification facts as JSON bytes. */
|
|
137
140
|
export function serializeVerification(value) {
|
|
138
141
|
const r = verificationFacts(value);
|
|
139
142
|
if (!r.ok)
|
|
@@ -147,6 +150,6 @@ export function serializeVerification(value) {
|
|
|
147
150
|
: v && typeof v === "object"
|
|
148
151
|
? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, encode(x)]))
|
|
149
152
|
: v;
|
|
150
|
-
return
|
|
153
|
+
return ok(encodeUtf8(JSON.stringify(encode(r.value))));
|
|
151
154
|
}
|
|
152
155
|
import { encodeBase64Url as base64url } from "./bytes.js";
|
package/dist/verify-quorum.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { type QuorumVerification } from "./quorum/verification.ts";
|
|
2
2
|
import { type Result } from "./result.ts";
|
|
3
|
+
/** Verify bounded HTTP signatures and evaluate the configured quorum policy. */
|
|
3
4
|
export declare function verifyQuorum(message: unknown, quorum: unknown, options: unknown): Promise<Result<QuorumVerification>>;
|
package/dist/verify-quorum.js
CHANGED
|
@@ -9,6 +9,7 @@ import { evaluateQuorum } from "./quorum/evaluation.js";
|
|
|
9
9
|
import { completeQuorum, } from "./quorum/verification.js";
|
|
10
10
|
import { custodyError, isRequestSealError } from "./errors/types.js";
|
|
11
11
|
import { ok, err } from "./result.js";
|
|
12
|
+
/** Verify bounded HTTP signatures and evaluate the configured quorum policy. */
|
|
12
13
|
export async function verifyQuorum(message, quorum, options) {
|
|
13
14
|
try {
|
|
14
15
|
const a = snapshotOptions(options, ["acceptSignature", "context"]);
|
package/dist/verify.d.ts
CHANGED
|
@@ -4,7 +4,10 @@ import { KeyIdentity } from "./key_identity.ts";
|
|
|
4
4
|
import { build } from "./signature-base/index.ts";
|
|
5
5
|
import { type Verification } from "./verification.ts";
|
|
6
6
|
import type { InnerList, Item } from "./structured-fields/index.ts";
|
|
7
|
+
import type { ReplayFacts } from "./replay-port.ts";
|
|
7
8
|
import { type Result } from "./result.ts";
|
|
9
|
+
/** Internal coverage/freshness pipeline shared by selected verification and preflight. */
|
|
10
|
+
export declare function authenticationPreflight(input: InnerList, components: InnerList, extra: Policy["extraComponents"], freshnessPolicy: Policy["freshness"] | (() => Policy["freshness"]), context: Context): Promise<Verification["freshness"]>;
|
|
8
11
|
/** Internal shared commit boundary; profile facts are supplied only after authentication. */
|
|
9
12
|
export declare function commitReplay<F>(facts: F, retainUntil: number, policy: Omit<import('./policy.ts').ReplayPolicy, 'commitment'> & {
|
|
10
13
|
commitment: (facts: F, context: Context) => Result<Uint8Array> | Promise<Result<Uint8Array>>;
|
|
@@ -16,6 +19,8 @@ type ParsedCandidate = Readonly<{
|
|
|
16
19
|
signature: Item;
|
|
17
20
|
baseCache: BaseCache;
|
|
18
21
|
}>;
|
|
22
|
+
export declare function verifyLabel(message: unknown, policy: unknown, options: unknown, observeIdentity?: (identity: KeyIdentity) => void, parsed?: ParsedCandidate, profile?: ReplayFacts["profile"]): Promise<Result<Verification>>;
|
|
23
|
+
/** Verify one HTTP signature under an explicit branded policy. */
|
|
19
24
|
export declare function verify(message: unknown, policy: unknown, options: unknown): Promise<Result<Verification>>;
|
|
20
25
|
/** Internal composition of the single-label pipeline; identities stay private. */
|
|
21
26
|
export declare function verifyCandidate(message: unknown, policy: Policy, options: unknown, parsed?: ParsedCandidate): Promise<Result<Readonly<{
|