@verax-ai/proxy 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/dist/approvals.d.ts +91 -0
- package/dist/approvals.js +282 -0
- package/dist/checkpoints.d.ts +3 -0
- package/dist/checkpoints.js +31 -0
- package/dist/disk.d.ts +6 -0
- package/dist/disk.js +13 -0
- package/dist/explain.d.ts +13 -0
- package/dist/explain.js +211 -0
- package/dist/hash.d.ts +4 -0
- package/dist/hash.js +10 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +17 -0
- package/dist/inputs.d.ts +13 -0
- package/dist/inputs.js +49 -0
- package/dist/ledger.d.ts +130 -0
- package/dist/ledger.js +683 -0
- package/dist/policy.d.ts +37 -0
- package/dist/policy.js +265 -0
- package/dist/proxy.d.ts +11 -0
- package/dist/proxy.js +533 -0
- package/dist/reconcile.d.ts +81 -0
- package/dist/reconcile.js +420 -0
- package/dist/spoken-reason.d.ts +1 -0
- package/dist/spoken-reason.js +9 -0
- package/dist/tenant.d.ts +12 -0
- package/dist/tenant.js +18 -0
- package/dist/types.d.ts +189 -0
- package/dist/types.js +1 -0
- package/package.json +37 -0
- package/policy/default.json +30 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { createProxy, LedgerDenyUnrecorded } from "./proxy.ts";
|
|
2
|
+
export { loadPolicy } from "./policy.ts";
|
|
3
|
+
export { FileLedger, MemoryLedger } from "./ledger.ts";
|
|
4
|
+
export { explain } from "./explain.ts";
|
|
5
|
+
export { approvePending, approvalsLogFor, enqueueApprovalCommand, loadApprovalsFromDir } from "./approvals.ts";
|
|
6
|
+
export { loadEffectsFromDir, parseCardCsv, parseChannelJsonl, reconcile } from "./reconcile.ts";
|
|
7
|
+
export { tenantKey } from "./tenant.ts";
|
|
8
|
+
export { diskProbe } from "./disk.ts";
|
|
9
|
+
export { checkpointsPath } from "./checkpoints.ts";
|
|
10
|
+
export { signEffectAttestation } from "./ledger.ts";
|
|
11
|
+
export { spokenReason } from "./spoken-reason.ts";
|
|
12
|
+
export type { ApprovalRow, ApproveResult } from "./approvals.ts";
|
|
13
|
+
export type { CardCsvOpts, ChannelRow, ReconcileReport } from "./reconcile.ts";
|
|
14
|
+
export type { EffectSigner, ExplainChain, ExplainPair, ExplainFinding, ExplainOpts, ExplainResult, ExplainTrustRoot, ExplainWarning, ExtractWindow, Ledger, LedgerEffect, Policy, PolicyDecision, Principal, ProxyDeps, RecordSigner, ToolCall, ToolResult, WitnessClass, } from "./types.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { createProxy, LedgerDenyUnrecorded } from "./proxy.js";
|
|
2
|
+
export { loadPolicy } from "./policy.js";
|
|
3
|
+
export { FileLedger, MemoryLedger } from "./ledger.js";
|
|
4
|
+
export { explain } from "./explain.js";
|
|
5
|
+
export { approvePending, approvalsLogFor, enqueueApprovalCommand, loadApprovalsFromDir } from "./approvals.js";
|
|
6
|
+
export { loadEffectsFromDir, parseCardCsv, parseChannelJsonl, reconcile } from "./reconcile.js";
|
|
7
|
+
export { tenantKey } from "./tenant.js";
|
|
8
|
+
// The body writes checkpoints and signs its own effect attestations. Both were
|
|
9
|
+
// reached through a relative path into this package, which only exists inside
|
|
10
|
+
// this repository: a published body would have imported a file that is not there.
|
|
11
|
+
// The disk seam is public for the same reason: a caller that drives the body
|
|
12
|
+
// through this package must be able to inject a full disk into the very
|
|
13
|
+
// instance the proxy uses. Deep imports are not in the exports map.
|
|
14
|
+
export { diskProbe } from "./disk.js";
|
|
15
|
+
export { checkpointsPath } from "./checkpoints.js";
|
|
16
|
+
export { signEffectAttestation } from "./ledger.js";
|
|
17
|
+
export { spokenReason } from "./spoken-reason.js";
|
package/dist/inputs.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DecisionInputs, InputsLog } from "./types.ts";
|
|
2
|
+
export declare class MemoryInputsLog implements InputsLog {
|
|
3
|
+
private readonly rows;
|
|
4
|
+
append(ref: string, inputs: DecisionInputs): Promise<void>;
|
|
5
|
+
get(ref: string): Promise<DecisionInputs | null>;
|
|
6
|
+
}
|
|
7
|
+
export declare class FileInputsLog implements InputsLog {
|
|
8
|
+
private readonly dir;
|
|
9
|
+
constructor(dir: string);
|
|
10
|
+
append(ref: string, inputs: DecisionInputs): Promise<void>;
|
|
11
|
+
get(ref: string): Promise<DecisionInputs | null>;
|
|
12
|
+
}
|
|
13
|
+
export declare function inputsLogFor(ledger: object): InputsLog;
|
package/dist/inputs.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { appendDurable, ledgerFs } from "./ledger.js";
|
|
3
|
+
export class MemoryInputsLog {
|
|
4
|
+
rows = new Map();
|
|
5
|
+
async append(ref, inputs) {
|
|
6
|
+
this.rows.set(ref, inputs);
|
|
7
|
+
}
|
|
8
|
+
async get(ref) {
|
|
9
|
+
return this.rows.get(ref) ?? null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class FileInputsLog {
|
|
13
|
+
dir;
|
|
14
|
+
constructor(dir) {
|
|
15
|
+
this.dir = dir;
|
|
16
|
+
}
|
|
17
|
+
async append(ref, inputs) {
|
|
18
|
+
await appendDurable(join(this.dir, "inputs.jsonl"), `${JSON.stringify({ ref, inputs })}\n`);
|
|
19
|
+
}
|
|
20
|
+
async get(ref) {
|
|
21
|
+
let text;
|
|
22
|
+
try {
|
|
23
|
+
text = await ledgerFs.readFile(join(this.dir, "inputs.jsonl"), "utf8");
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
if (err.code === "ENOENT")
|
|
27
|
+
return null;
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
let found = null;
|
|
31
|
+
for (const line of text.split("\n")) {
|
|
32
|
+
if (line === "")
|
|
33
|
+
continue;
|
|
34
|
+
const row = JSON.parse(line);
|
|
35
|
+
if (row.ref === ref)
|
|
36
|
+
found = row.inputs;
|
|
37
|
+
}
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const STASH = Symbol.for("verax.inputsLog");
|
|
42
|
+
export function inputsLogFor(ledger) {
|
|
43
|
+
const bag = ledger;
|
|
44
|
+
if (bag[STASH])
|
|
45
|
+
return bag[STASH];
|
|
46
|
+
const log = typeof bag.dir === "string" ? new FileInputsLog(bag.dir) : new MemoryInputsLog();
|
|
47
|
+
bag[STASH] = log;
|
|
48
|
+
return log;
|
|
49
|
+
}
|
package/dist/ledger.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { open, readFile } from "node:fs/promises";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
/** I/O seam so append-cost tests can count rereads without mocking node:fs. */
|
|
4
|
+
export declare const ledgerFs: {
|
|
5
|
+
readFile: typeof readFile;
|
|
6
|
+
readFileSync: typeof readFileSync;
|
|
7
|
+
open: typeof open;
|
|
8
|
+
};
|
|
9
|
+
import { type EffectRow, type SignedEffectExtract } from "@cedulon/effect-extract";
|
|
10
|
+
import type { EffectSigner, ExtractWindow, Ledger, LedgerEffect, WitnessClass } from "./types.ts";
|
|
11
|
+
import type { DecisionKind, SignedDecisionRecord } from "@cedulon/core";
|
|
12
|
+
export type PermissionCheck = "owner-only" | "not checked on this platform";
|
|
13
|
+
/** Write then fsync so a crash cannot drop a committed line. */
|
|
14
|
+
export declare function appendDurable(path: string, line: string): Promise<void>;
|
|
15
|
+
export type RemoteWitnessSign = (row: EffectRow, resultHash: string | undefined) => Promise<Pick<LedgerEffect, "receipt" | "attestation" | "witnessClass"> | null>;
|
|
16
|
+
export declare function signEffectAttestation(row: EffectRow, witnessClass: WitnessClass, resultHash: string | undefined, signer: EffectSigner): Pick<LedgerEffect, "receipt" | "attestation">;
|
|
17
|
+
/** Slim index row. The Ledger interface stays closed. */
|
|
18
|
+
export type DecisionIndexRow = {
|
|
19
|
+
ref: string;
|
|
20
|
+
requestHash: string;
|
|
21
|
+
decision: DecisionKind;
|
|
22
|
+
reasonCode: string;
|
|
23
|
+
subject: string;
|
|
24
|
+
policyHash: string;
|
|
25
|
+
timestampMs: number;
|
|
26
|
+
};
|
|
27
|
+
export type ResolutionHit = {
|
|
28
|
+
ref: string;
|
|
29
|
+
kind: "allow" | "expired";
|
|
30
|
+
};
|
|
31
|
+
export declare class MemoryLedger implements Ledger {
|
|
32
|
+
readonly permissionCheck: PermissionCheck;
|
|
33
|
+
effectSigner?: EffectSigner;
|
|
34
|
+
private readonly _decisions;
|
|
35
|
+
private readonly _effects;
|
|
36
|
+
private readonly byRef;
|
|
37
|
+
private readonly resolvedBy;
|
|
38
|
+
private readonly reauthByHash;
|
|
39
|
+
private readonly countedAt;
|
|
40
|
+
countsReadable: boolean;
|
|
41
|
+
private readonly q;
|
|
42
|
+
lookupByRef(ref: string): DecisionIndexRow | null;
|
|
43
|
+
noteTenantRef(key: string, ref: string): void;
|
|
44
|
+
lookupResolvedBy(deferRef: string): ResolutionHit | null;
|
|
45
|
+
noteResolution(deferRef: string, hit: ResolutionHit): void;
|
|
46
|
+
lookupReauthByHash(requestHash: string): string | null;
|
|
47
|
+
countedTimes(): number[];
|
|
48
|
+
hasPrimaryEffect(ref: string): boolean;
|
|
49
|
+
appendDecision(signed: SignedDecisionRecord): Promise<void>;
|
|
50
|
+
appendDecisionChained(build: (prevRecordHash: string | null) => SignedDecisionRecord): Promise<void>;
|
|
51
|
+
appendEffect(row: EffectRow, witnessClass?: WitnessClass, resultHash?: string): Promise<void>;
|
|
52
|
+
private appendEffectUnlocked;
|
|
53
|
+
decisions(): Promise<SignedDecisionRecord[]>;
|
|
54
|
+
effects(): Promise<LedgerEffect[]>;
|
|
55
|
+
lastDecisionHash(): Promise<string | null>;
|
|
56
|
+
exportExtract(window: ExtractWindow, signer: EffectSigner): Promise<SignedEffectExtract>;
|
|
57
|
+
}
|
|
58
|
+
export declare class FileLedger implements Ledger {
|
|
59
|
+
readonly permissionCheck: PermissionCheck;
|
|
60
|
+
readonly dir: string;
|
|
61
|
+
effectSigner?: EffectSigner;
|
|
62
|
+
/** Optional signer in another process. Null means stay `self`. */
|
|
63
|
+
remoteWitness?: RemoteWitnessSign;
|
|
64
|
+
private readonly decisionsPath;
|
|
65
|
+
private readonly effectsPath;
|
|
66
|
+
private readonly lockPath;
|
|
67
|
+
private readonly q;
|
|
68
|
+
private readonly token;
|
|
69
|
+
private closed;
|
|
70
|
+
private lost;
|
|
71
|
+
private tailHash;
|
|
72
|
+
private readonly effectRefs;
|
|
73
|
+
private readonly byRef;
|
|
74
|
+
private readonly resolvedBy;
|
|
75
|
+
private readonly reauthByHash;
|
|
76
|
+
private readonly countedAt;
|
|
77
|
+
countsReadable: boolean;
|
|
78
|
+
private readonly copyDir;
|
|
79
|
+
private readonly heartbeatPath;
|
|
80
|
+
private decisionCount;
|
|
81
|
+
private effectCount;
|
|
82
|
+
constructor(dir: string);
|
|
83
|
+
/** After lock handoff a new instance reloads; the lost owner cannot append. */
|
|
84
|
+
private loadCaches;
|
|
85
|
+
/** Pair inputs.jsonl with decisions so a restart keeps per-tenant `_ref` keys. */
|
|
86
|
+
private loadTenantRefs;
|
|
87
|
+
/** Single pass over inputs.jsonl. FileInputsLog itself stays cache-less. */
|
|
88
|
+
private loadResolvedBy;
|
|
89
|
+
private lockBody;
|
|
90
|
+
private ownsLock;
|
|
91
|
+
/** Lock file on disk, not a process counter. */
|
|
92
|
+
lockStatus(): "held" | "free";
|
|
93
|
+
private markLost;
|
|
94
|
+
private assertOwned;
|
|
95
|
+
private lockedError;
|
|
96
|
+
private acquireLock;
|
|
97
|
+
close(): void;
|
|
98
|
+
appendDecision(signed: SignedDecisionRecord): Promise<void>;
|
|
99
|
+
appendDecisionChained(build: (prevRecordHash: string | null) => SignedDecisionRecord): Promise<void>;
|
|
100
|
+
appendEffect(row: EffectRow, witnessClass?: WitnessClass, resultHash?: string): Promise<void>;
|
|
101
|
+
private appendEffectUnlocked;
|
|
102
|
+
decisions(): Promise<SignedDecisionRecord[]>;
|
|
103
|
+
effects(): Promise<LedgerEffect[]>;
|
|
104
|
+
lastDecisionHash(): Promise<string | null>;
|
|
105
|
+
private lastDecisionHashUnlocked;
|
|
106
|
+
exportExtract(window: ExtractWindow, signer: EffectSigner): Promise<SignedEffectExtract>;
|
|
107
|
+
lookupByRef(ref: string): DecisionIndexRow | null;
|
|
108
|
+
noteTenantRef(key: string, ref: string): void;
|
|
109
|
+
lookupResolvedBy(deferRef: string): ResolutionHit | null;
|
|
110
|
+
noteResolution(deferRef: string, hit: ResolutionHit): void;
|
|
111
|
+
lookupReauthByHash(requestHash: string): string | null;
|
|
112
|
+
countedTimes(): number[];
|
|
113
|
+
hasPrimaryEffect(ref: string): boolean;
|
|
114
|
+
private pulse;
|
|
115
|
+
private storeEffect;
|
|
116
|
+
}
|
|
117
|
+
export declare function lookupDecisionByRef(ledger: Ledger, ref: string, key?: string): Promise<DecisionIndexRow | null>;
|
|
118
|
+
export declare function noteTenantRef(ledger: Ledger, key: string, ref: string): void;
|
|
119
|
+
export declare function lookupResolvedBy(ledger: Ledger, deferRef: string): ResolutionHit | null;
|
|
120
|
+
export declare function noteResolution(ledger: Ledger, deferRef: string, hit: ResolutionHit): void;
|
|
121
|
+
export declare function countedWork(ledger: Ledger, nowMs: number): {
|
|
122
|
+
ok: true;
|
|
123
|
+
minute: number;
|
|
124
|
+
day: number;
|
|
125
|
+
} | {
|
|
126
|
+
ok: false;
|
|
127
|
+
};
|
|
128
|
+
export declare function lookupReauthByHash(ledger: Ledger, requestHash: string): Promise<string | null>;
|
|
129
|
+
export declare function hasPrimaryEffect(ledger: Ledger, ref: string): Promise<boolean>;
|
|
130
|
+
export declare function witnessClassSummary(effects: readonly LedgerEffect[]): Record<WitnessClass, number>;
|