@kyaki/agents 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 +35 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +93 -0
- package/dist/approvals.js.map +1 -0
- package/dist/auditor.d.ts +104 -0
- package/dist/auditor.d.ts.map +1 -0
- package/dist/auditor.js +250 -0
- package/dist/auditor.js.map +1 -0
- package/dist/continuous-auditor.d.ts +38 -0
- package/dist/continuous-auditor.d.ts.map +1 -0
- package/dist/continuous-auditor.js +52 -0
- package/dist/continuous-auditor.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/market.d.ts +10 -0
- package/dist/market.d.ts.map +1 -0
- package/dist/market.js +10 -0
- package/dist/market.js.map +1 -0
- package/dist/procurer.d.ts +54 -0
- package/dist/procurer.d.ts.map +1 -0
- package/dist/procurer.js +142 -0
- package/dist/procurer.js.map +1 -0
- package/dist/steward.d.ts +89 -0
- package/dist/steward.d.ts.map +1 -0
- package/dist/steward.js +121 -0
- package/dist/steward.js.map +1 -0
- package/dist/treasury.d.ts +134 -0
- package/dist/treasury.d.ts.map +1 -0
- package/dist/treasury.js +346 -0
- package/dist/treasury.js.map +1 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +34 -0
- package/src/approvals.ts +111 -0
- package/src/auditor.ts +342 -0
- package/src/continuous-auditor.ts +68 -0
- package/src/index.ts +31 -0
- package/src/market.ts +11 -0
- package/src/procurer.ts +183 -0
- package/src/steward.ts +168 -0
- package/src/treasury.ts +458 -0
- package/src/types.ts +57 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Identity, type SpendMandate, type TransactionIntent } from '@kyaki/core';
|
|
2
|
+
import type { HumanApproval } from '@kyaki/policy';
|
|
3
|
+
import type { ApprovalRequest, ProcurementNeed, VendorOffer } from './types.js';
|
|
4
|
+
export interface SignedApproval extends HumanApproval {
|
|
5
|
+
at: string;
|
|
6
|
+
signature: string;
|
|
7
|
+
}
|
|
8
|
+
/** Produce a CFO countersignature over the canonical approval document. The
|
|
9
|
+
* single signer used by every approval inbox (procurement + treasury), so the
|
|
10
|
+
* signed shape never diverges from what verifyApproval expects. */
|
|
11
|
+
export declare function signApproval(intentId: string, approver: Identity, at?: string): SignedApproval;
|
|
12
|
+
export declare function verifyApproval(approval: SignedApproval): boolean;
|
|
13
|
+
export declare class ApprovalInbox {
|
|
14
|
+
private requests;
|
|
15
|
+
submit(input: {
|
|
16
|
+
intent: TransactionIntent;
|
|
17
|
+
mandate: SpendMandate;
|
|
18
|
+
need: ProcurementNeed;
|
|
19
|
+
offer: VendorOffer;
|
|
20
|
+
reason: string;
|
|
21
|
+
}): ApprovalRequest;
|
|
22
|
+
get(id: string): ApprovalRequest | undefined;
|
|
23
|
+
pending(): ApprovalRequest[];
|
|
24
|
+
all(): ApprovalRequest[];
|
|
25
|
+
approve(id: string, approver: Identity): SignedApproval;
|
|
26
|
+
reject(id: string, approver: Identity): ApprovalRequest;
|
|
27
|
+
/** Accept a countersignature produced OUTSIDE the inbox — e.g. signed in the
|
|
28
|
+
* CFO's browser with their own key — as the approval decision. The caller is
|
|
29
|
+
* expected to have already run verifyApproval(); this only binds the decision
|
|
30
|
+
* to the request (and refuses if the signature is for a different intent). */
|
|
31
|
+
acceptSignature(id: string, signed: SignedApproval): boolean;
|
|
32
|
+
/** Exactly-once gate. Returns true the FIRST time only. */
|
|
33
|
+
markExecuted(id: string): boolean;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=approvals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,QAAQ,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EACzD,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEhF,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;oEAEoE;AACpE,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,EAAE,GAAE,MAAiC,GACpC,cAAc,CAGhB;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAQhE;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAsC;IAEtD,MAAM,CAAC,KAAK,EAAE;QACZ,MAAM,EAAE,iBAAiB,CAAC;QAAC,OAAO,EAAE,YAAY,CAAC;QAAC,IAAI,EAAE,eAAe,CAAC;QACxE,KAAK,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;KACpC,GAAG,eAAe;IAWnB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAC5C,OAAO,IAAI,eAAe,EAAE;IAC5B,GAAG,IAAI,eAAe,EAAE;IAExB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,cAAc;IAWvD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,eAAe;IAUvD;;;mFAG+E;IAC/E,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,OAAO;IAU5D,2DAA2D;IAC3D,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;CAMlC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* approvals.ts — The human countersignature workflow.
|
|
3
|
+
*
|
|
4
|
+
* Approval is not a button click recorded in a database row — it is an
|
|
5
|
+
* Ed25519 SIGNATURE by the approver's key over a canonical approval document
|
|
6
|
+
* binding (intentId, approvedBy, at). Exactly-once execution is enforced by
|
|
7
|
+
* markExecuted, which flips state before the kernel is touched.
|
|
8
|
+
*/
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { canonicalBytes, fromBase58, publicKeyFromDid, sign, toBase58, verifySignature, } from '@kyaki/core';
|
|
11
|
+
function approvalDocument(intentId, approvedBy, at) {
|
|
12
|
+
return { type: 'KyaHumanApproval', intentId, approvedBy, at };
|
|
13
|
+
}
|
|
14
|
+
/** Produce a CFO countersignature over the canonical approval document. The
|
|
15
|
+
* single signer used by every approval inbox (procurement + treasury), so the
|
|
16
|
+
* signed shape never diverges from what verifyApproval expects. */
|
|
17
|
+
export function signApproval(intentId, approver, at = new Date().toISOString()) {
|
|
18
|
+
const doc = approvalDocument(intentId, approver.did, at);
|
|
19
|
+
return { intentId, approvedBy: approver.did, at, signature: toBase58(sign(canonicalBytes(doc), approver.privateKey)) };
|
|
20
|
+
}
|
|
21
|
+
export function verifyApproval(approval) {
|
|
22
|
+
try {
|
|
23
|
+
const publicKey = publicKeyFromDid(approval.approvedBy);
|
|
24
|
+
const doc = approvalDocument(approval.intentId, approval.approvedBy, approval.at);
|
|
25
|
+
return verifySignature(fromBase58(approval.signature), canonicalBytes(doc), publicKey);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class ApprovalInbox {
|
|
32
|
+
requests = new Map();
|
|
33
|
+
submit(input) {
|
|
34
|
+
const request = {
|
|
35
|
+
id: `apr_${randomUUID().slice(0, 8)}`,
|
|
36
|
+
intent: input.intent, mandate: input.mandate, need: input.need,
|
|
37
|
+
offer: input.offer, reason: input.reason,
|
|
38
|
+
submittedAt: new Date().toISOString(), status: 'pending',
|
|
39
|
+
};
|
|
40
|
+
this.requests.set(request.id, request);
|
|
41
|
+
return request;
|
|
42
|
+
}
|
|
43
|
+
get(id) { return this.requests.get(id); }
|
|
44
|
+
pending() { return [...this.requests.values()].filter((r) => r.status === 'pending'); }
|
|
45
|
+
all() { return [...this.requests.values()]; }
|
|
46
|
+
approve(id, approver) {
|
|
47
|
+
const request = this.requests.get(id);
|
|
48
|
+
if (!request)
|
|
49
|
+
throw new Error(`No approval request ${id}`);
|
|
50
|
+
if (request.status !== 'pending')
|
|
51
|
+
throw new Error(`Approval ${id} is ${request.status}, not pending`);
|
|
52
|
+
const signed = signApproval(request.intent.id, approver);
|
|
53
|
+
request.status = 'approved';
|
|
54
|
+
request.decidedBy = signed.approvedBy;
|
|
55
|
+
request.decidedAt = signed.at;
|
|
56
|
+
return signed;
|
|
57
|
+
}
|
|
58
|
+
reject(id, approver) {
|
|
59
|
+
const request = this.requests.get(id);
|
|
60
|
+
if (!request)
|
|
61
|
+
throw new Error(`No approval request ${id}`);
|
|
62
|
+
if (request.status !== 'pending')
|
|
63
|
+
throw new Error(`Approval ${id} is ${request.status}, not pending`);
|
|
64
|
+
request.status = 'rejected';
|
|
65
|
+
request.decidedBy = approver.did;
|
|
66
|
+
request.decidedAt = new Date().toISOString();
|
|
67
|
+
return request;
|
|
68
|
+
}
|
|
69
|
+
/** Accept a countersignature produced OUTSIDE the inbox — e.g. signed in the
|
|
70
|
+
* CFO's browser with their own key — as the approval decision. The caller is
|
|
71
|
+
* expected to have already run verifyApproval(); this only binds the decision
|
|
72
|
+
* to the request (and refuses if the signature is for a different intent). */
|
|
73
|
+
acceptSignature(id, signed) {
|
|
74
|
+
const request = this.requests.get(id);
|
|
75
|
+
if (!request || request.status !== 'pending')
|
|
76
|
+
return false;
|
|
77
|
+
if (signed.intentId !== request.intent.id)
|
|
78
|
+
return false;
|
|
79
|
+
request.status = 'approved';
|
|
80
|
+
request.decidedBy = signed.approvedBy;
|
|
81
|
+
request.decidedAt = signed.at;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
/** Exactly-once gate. Returns true the FIRST time only. */
|
|
85
|
+
markExecuted(id) {
|
|
86
|
+
const request = this.requests.get(id);
|
|
87
|
+
if (!request || request.status !== 'approved')
|
|
88
|
+
return false;
|
|
89
|
+
request.status = 'executed';
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auditor.ts — The Auditor: the third agent on the Mandate OS, and the only
|
|
3
|
+
* one that never spends.
|
|
4
|
+
*
|
|
5
|
+
* Where the Procurer pushes money outward and the Treasurer moves the balance
|
|
6
|
+
* sheet, the Auditor *proves the whole fleet stayed inside its authority*. It
|
|
7
|
+
* is the agent that operationalizes the project's central claim — "the books
|
|
8
|
+
* are self-auditing" — by turning it into a concrete, signed artifact.
|
|
9
|
+
*
|
|
10
|
+
* It composes existing rings; it invents no new kernel primitive:
|
|
11
|
+
* L0 AuditLog.verifyChain — is the record itself tamper-free?
|
|
12
|
+
* L0 verifyTransaction — does each committed spend STILL verify,
|
|
13
|
+
* re-run against state as of its own commit?
|
|
14
|
+
* L1 OrgSpendLedger semantics — did aggregate exposure breach the org cap?
|
|
15
|
+
* L1 AutonomyLadder.demote — punish the agent the instant a provable
|
|
16
|
+
* cryptographic anomaly is found.
|
|
17
|
+
*
|
|
18
|
+
* The audit produces a `KyaAuditAttestation`: an Ed25519 signature by the
|
|
19
|
+
* auditor's own key over the canonical set of findings + the chain head. Like
|
|
20
|
+
* a mandate, an intent, or a CFO approval, the audit-of-record is a verifiable
|
|
21
|
+
* object — not a database row asserting "trust me."
|
|
22
|
+
*
|
|
23
|
+
* Reconciliation principle (inherited from the Procurer's savings report): if
|
|
24
|
+
* the hash chain does not verify, the committed record cannot be trusted, so
|
|
25
|
+
* the report says so loudly rather than quietly reporting clean.
|
|
26
|
+
*/
|
|
27
|
+
import { type AgentKeys, type AuditLog, type SpendMandate, type TransactionIntent } from '@kyaki/core';
|
|
28
|
+
import { AutonomyLadder, type SpendPolicy } from '@kyaki/policy';
|
|
29
|
+
export type Severity = 'info' | 'warning' | 'violation' | 'critical';
|
|
30
|
+
export interface Finding {
|
|
31
|
+
code: string;
|
|
32
|
+
severity: Severity;
|
|
33
|
+
detail: string;
|
|
34
|
+
agentDid?: string;
|
|
35
|
+
mandateId?: string;
|
|
36
|
+
intentId?: string;
|
|
37
|
+
}
|
|
38
|
+
/** A committed spend, presented to the Auditor as the verifiable pair the
|
|
39
|
+
* kernel originally checked: the agent's signed intent + the principal's
|
|
40
|
+
* signed mandate it named. */
|
|
41
|
+
export interface CommittedSpend {
|
|
42
|
+
intent: TransactionIntent;
|
|
43
|
+
mandate: SpendMandate;
|
|
44
|
+
}
|
|
45
|
+
/** A revocation event with a timestamp. The live RevocationStore is timeless
|
|
46
|
+
* (boolean); for forensic "did the spend happen AFTER revocation?" the
|
|
47
|
+
* Auditor needs the revocation's `at`. */
|
|
48
|
+
export interface RevocationRecord {
|
|
49
|
+
mandateId: string;
|
|
50
|
+
at: string;
|
|
51
|
+
}
|
|
52
|
+
export interface AuditAttestation {
|
|
53
|
+
type: 'KyaAuditAttestation';
|
|
54
|
+
auditor: string;
|
|
55
|
+
chainHead: string;
|
|
56
|
+
at: string;
|
|
57
|
+
findings: Finding[];
|
|
58
|
+
signature: string;
|
|
59
|
+
}
|
|
60
|
+
export interface AuditReport {
|
|
61
|
+
at: string;
|
|
62
|
+
chainValid: boolean;
|
|
63
|
+
clean: boolean;
|
|
64
|
+
findings: Finding[];
|
|
65
|
+
summary: Record<Severity, number>;
|
|
66
|
+
reconciledMandates: number;
|
|
67
|
+
reconciledSpends: number;
|
|
68
|
+
demoted: string[];
|
|
69
|
+
attestation: AuditAttestation;
|
|
70
|
+
}
|
|
71
|
+
export interface AuditInput {
|
|
72
|
+
committed: CommittedSpend[];
|
|
73
|
+
revocations?: RevocationRecord[];
|
|
74
|
+
}
|
|
75
|
+
export interface AuditorConfig {
|
|
76
|
+
auditorKeys: AgentKeys;
|
|
77
|
+
/** The hash chain under examination (the fleet's audit-of-record). */
|
|
78
|
+
audit: AuditLog;
|
|
79
|
+
/** Org policy — only `orgLimits.dailyCap` is consulted, for aggregate exposure. */
|
|
80
|
+
policy?: SpendPolicy;
|
|
81
|
+
/** When present, agents caught in a security anomaly are demoted. */
|
|
82
|
+
ladder?: AutonomyLadder;
|
|
83
|
+
/** Where the Auditor anchors its OWN result, so the audit is itself audited. */
|
|
84
|
+
oversight?: AuditLog;
|
|
85
|
+
/** Chain event types that denote a committed spend, for chain↔object
|
|
86
|
+
* reconciliation. Defaults to the Procurer's commit events; pass the
|
|
87
|
+
* Treasurer's (or any agent's) commit event types to widen coverage. */
|
|
88
|
+
committedEventTypes?: string[];
|
|
89
|
+
now?: Date;
|
|
90
|
+
}
|
|
91
|
+
/** Recompute and check an attestation's signature. Tampering with any finding,
|
|
92
|
+
* the chain head, or the timestamp invalidates it — exactly like a mandate. */
|
|
93
|
+
export declare function verifyAuditAttestation(att: AuditAttestation): boolean;
|
|
94
|
+
export declare class AuditorAgent {
|
|
95
|
+
private readonly cfg;
|
|
96
|
+
constructor(cfg: AuditorConfig);
|
|
97
|
+
private now;
|
|
98
|
+
/** The intent id a commit-class chain event points at (txnId or intentId). */
|
|
99
|
+
private intentIdOf;
|
|
100
|
+
private commitTypes;
|
|
101
|
+
audit(input: AuditInput): Promise<AuditReport>;
|
|
102
|
+
private signAttestation;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=auditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditor.d.ts","sourceRoot":"","sources":["../src/auditor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAGL,KAAK,SAAS,EAAmB,KAAK,QAAQ,EAAE,KAAK,YAAY,EACjE,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAajE,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAErE,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;+BAE+B;AAC/B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;2CAE2C;AAC3C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAClC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,gBAAgB,CAAC;CAC/B;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,SAAS,CAAC;IACvB,sEAAsE;IACtE,KAAK,EAAE,QAAQ,CAAC;IAChB,mFAAmF;IACnF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,qEAAqE;IACrE,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,gFAAgF;IAChF,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB;;6EAEyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAOD;gFACgF;AAChF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAQrE;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,aAAa;IAE/C,OAAO,CAAC,GAAG;IAEX,8EAA8E;IAC9E,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAIb,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAyLpD,OAAO,CAAC,eAAe;CASxB"}
|
package/dist/auditor.js
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auditor.ts — The Auditor: the third agent on the Mandate OS, and the only
|
|
3
|
+
* one that never spends.
|
|
4
|
+
*
|
|
5
|
+
* Where the Procurer pushes money outward and the Treasurer moves the balance
|
|
6
|
+
* sheet, the Auditor *proves the whole fleet stayed inside its authority*. It
|
|
7
|
+
* is the agent that operationalizes the project's central claim — "the books
|
|
8
|
+
* are self-auditing" — by turning it into a concrete, signed artifact.
|
|
9
|
+
*
|
|
10
|
+
* It composes existing rings; it invents no new kernel primitive:
|
|
11
|
+
* L0 AuditLog.verifyChain — is the record itself tamper-free?
|
|
12
|
+
* L0 verifyTransaction — does each committed spend STILL verify,
|
|
13
|
+
* re-run against state as of its own commit?
|
|
14
|
+
* L1 OrgSpendLedger semantics — did aggregate exposure breach the org cap?
|
|
15
|
+
* L1 AutonomyLadder.demote — punish the agent the instant a provable
|
|
16
|
+
* cryptographic anomaly is found.
|
|
17
|
+
*
|
|
18
|
+
* The audit produces a `KyaAuditAttestation`: an Ed25519 signature by the
|
|
19
|
+
* auditor's own key over the canonical set of findings + the chain head. Like
|
|
20
|
+
* a mandate, an intent, or a CFO approval, the audit-of-record is a verifiable
|
|
21
|
+
* object — not a database row asserting "trust me."
|
|
22
|
+
*
|
|
23
|
+
* Reconciliation principle (inherited from the Procurer's savings report): if
|
|
24
|
+
* the hash chain does not verify, the committed record cannot be trusted, so
|
|
25
|
+
* the report says so loudly rather than quietly reporting clean.
|
|
26
|
+
*/
|
|
27
|
+
import { canonicalBytes, fromBase58, publicKeyFromDid, sign, toBase58, verifySignature, verifyTransaction, MemorySpendStore, } from '@kyaki/core';
|
|
28
|
+
const DAY_MS = 24 * 3600 * 1000;
|
|
29
|
+
/** Kernel deny-reasons that prove cryptographic misbehavior by a named agent
|
|
30
|
+
* key — these, and only these, cost the agent a rung on the autonomy ladder. */
|
|
31
|
+
const SECURITY_REASONS = new Set([
|
|
32
|
+
'MANDATE_SIGNATURE_INVALID',
|
|
33
|
+
'INTENT_SIGNATURE_INVALID',
|
|
34
|
+
'AGENT_MISMATCH',
|
|
35
|
+
'MANDATE_ID_MISMATCH',
|
|
36
|
+
]);
|
|
37
|
+
const GENESIS = '0'.repeat(64);
|
|
38
|
+
const DEFAULT_COMMIT_TYPES = ['procurement.purchased', 'approval.executed'];
|
|
39
|
+
const EMPTY_SUMMARY = () => ({ info: 0, warning: 0, violation: 0, critical: 0 });
|
|
40
|
+
/** Recompute and check an attestation's signature. Tampering with any finding,
|
|
41
|
+
* the chain head, or the timestamp invalidates it — exactly like a mandate. */
|
|
42
|
+
export function verifyAuditAttestation(att) {
|
|
43
|
+
try {
|
|
44
|
+
const { signature, ...doc } = att;
|
|
45
|
+
const publicKey = publicKeyFromDid(att.auditor);
|
|
46
|
+
return verifySignature(fromBase58(signature), canonicalBytes(doc), publicKey);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export class AuditorAgent {
|
|
53
|
+
cfg;
|
|
54
|
+
constructor(cfg) {
|
|
55
|
+
this.cfg = cfg;
|
|
56
|
+
}
|
|
57
|
+
now() { return this.cfg.now ?? new Date(); }
|
|
58
|
+
/** The intent id a commit-class chain event points at (txnId or intentId). */
|
|
59
|
+
intentIdOf(event) {
|
|
60
|
+
return event.txnId
|
|
61
|
+
?? event.intentId;
|
|
62
|
+
}
|
|
63
|
+
commitTypes() {
|
|
64
|
+
return new Set(this.cfg.committedEventTypes ?? DEFAULT_COMMIT_TYPES);
|
|
65
|
+
}
|
|
66
|
+
async audit(input) {
|
|
67
|
+
const at = this.now().toISOString();
|
|
68
|
+
const findings = [];
|
|
69
|
+
const revokedAt = new Map();
|
|
70
|
+
for (const r of input.revocations ?? [])
|
|
71
|
+
revokedAt.set(r.mandateId, Date.parse(r.at));
|
|
72
|
+
// 1. Chain integrity. If the record is forged, nothing built on it is trustworthy.
|
|
73
|
+
const chainValid = this.cfg.audit.verifyChain();
|
|
74
|
+
if (!chainValid) {
|
|
75
|
+
findings.push({
|
|
76
|
+
code: 'CHAIN_BROKEN', severity: 'critical',
|
|
77
|
+
detail: 'Audit hash chain failed verification — the committed record has been tampered with; downstream reconciliation is not trustworthy.',
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// Order committed spends by their own timestamp so per-mandate cumulative
|
|
81
|
+
// and velocity re-checks see only what preceded each spend.
|
|
82
|
+
const ordered = input.committed
|
|
83
|
+
.map((c, i) => ({ c, i, t: Date.parse(c.intent.timestamp) }))
|
|
84
|
+
.sort((a, b) => (a.t - b.t) || (a.i - b.i));
|
|
85
|
+
const mandates = new Set();
|
|
86
|
+
const nonceSeen = new Map(); // nonce -> first intentId
|
|
87
|
+
const intentIdSeen = new Map();
|
|
88
|
+
// 2. Per-spend re-verification, AS OF the spend's own commit time.
|
|
89
|
+
for (let pos = 0; pos < ordered.length; pos++) {
|
|
90
|
+
const { c } = ordered[pos];
|
|
91
|
+
const { intent, mandate } = c;
|
|
92
|
+
mandates.add(mandate.id);
|
|
93
|
+
// Reconstruct mandate state as it stood just before this spend: every
|
|
94
|
+
// strictly-earlier committed spend on the SAME mandate (ordered is a
|
|
95
|
+
// stable timestamp sort, so positions < pos are exactly those).
|
|
96
|
+
const spendTime = new Date(Date.parse(intent.timestamp));
|
|
97
|
+
const spend = new MemorySpendStore();
|
|
98
|
+
for (let k = 0; k < pos; k++) {
|
|
99
|
+
const prior = ordered[k].c.intent;
|
|
100
|
+
if (prior.mandateId !== intent.mandateId)
|
|
101
|
+
continue;
|
|
102
|
+
await spend.record(prior.mandateId, prior.amount, prior.id, new Date(ordered[k].t));
|
|
103
|
+
}
|
|
104
|
+
const ctx = { spend, now: spendTime };
|
|
105
|
+
const res = await verifyTransaction(mandate, intent, ctx);
|
|
106
|
+
if (res.decision === 'deny') {
|
|
107
|
+
for (const reason of res.reasons) {
|
|
108
|
+
findings.push({
|
|
109
|
+
code: reason,
|
|
110
|
+
severity: SECURITY_REASONS.has(reason) ? 'critical' : 'violation',
|
|
111
|
+
detail: `Committed spend fails re-verification as of its own timestamp: ${reason}. The kernel should never have allowed it.`,
|
|
112
|
+
agentDid: intent.agent, mandateId: mandate.id, intentId: intent.id,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// 2b. Authority that has since lapsed (the spend was fine; the mandate is now dead).
|
|
117
|
+
if (Date.parse(mandate.validUntil) < this.now().getTime()) {
|
|
118
|
+
findings.push({
|
|
119
|
+
code: 'AUTHORITY_LAPSED', severity: 'warning',
|
|
120
|
+
detail: 'The mandate behind a committed spend has since expired. The spend was authorized when made; the authority is no longer live.',
|
|
121
|
+
agentDid: intent.agent, mandateId: mandate.id, intentId: intent.id,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// 2c. Spend AFTER revocation — a real breach.
|
|
125
|
+
const rev = revokedAt.get(mandate.id);
|
|
126
|
+
if (rev !== undefined && Date.parse(intent.timestamp) >= rev) {
|
|
127
|
+
findings.push({
|
|
128
|
+
code: 'SPEND_AFTER_REVOCATION', severity: 'critical',
|
|
129
|
+
detail: 'A spend committed at or after the mandate was revoked.',
|
|
130
|
+
agentDid: intent.agent, mandateId: mandate.id, intentId: intent.id,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// 3. Ledger-level duplicate detection: replay / double-spend that slipped in.
|
|
134
|
+
const priorNonce = nonceSeen.get(intent.nonce);
|
|
135
|
+
if (priorNonce && priorNonce !== intent.id) {
|
|
136
|
+
findings.push({
|
|
137
|
+
code: 'REPLAY_IN_LEDGER', severity: 'critical',
|
|
138
|
+
detail: `Duplicate nonce across committed intents (${priorNonce} and ${intent.id}) — a replay reached the ledger.`,
|
|
139
|
+
agentDid: intent.agent, mandateId: mandate.id, intentId: intent.id,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (!priorNonce) {
|
|
143
|
+
nonceSeen.set(intent.nonce, intent.id);
|
|
144
|
+
}
|
|
145
|
+
intentIdSeen.set(intent.id, (intentIdSeen.get(intent.id) ?? 0) + 1);
|
|
146
|
+
}
|
|
147
|
+
for (const [intentId, count] of intentIdSeen) {
|
|
148
|
+
if (count > 1) {
|
|
149
|
+
findings.push({
|
|
150
|
+
code: 'DUPLICATE_INTENT_ID', severity: 'critical',
|
|
151
|
+
detail: `Intent id ${intentId} appears ${count}× in the committed ledger.`,
|
|
152
|
+
intentId,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// 4. Aggregate org exposure (cross-mandate) within the rolling day.
|
|
157
|
+
const dailyCap = this.cfg.policy?.orgLimits?.dailyCap;
|
|
158
|
+
if (dailyCap !== undefined) {
|
|
159
|
+
const tNow = this.now().getTime();
|
|
160
|
+
const spentToday = input.committed
|
|
161
|
+
.filter((c) => tNow - Date.parse(c.intent.timestamp) < DAY_MS)
|
|
162
|
+
.reduce((s, c) => s + c.intent.amount, 0);
|
|
163
|
+
if (spentToday > dailyCap) {
|
|
164
|
+
findings.push({
|
|
165
|
+
code: 'ORG_EXPOSURE_BREACH', severity: 'violation',
|
|
166
|
+
detail: `Aggregate spend in the last 24h (${spentToday}) exceeds the org daily cap (${dailyCap}).`,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// 5. Coverage: the chain and the signed objects must reconcile, both ways.
|
|
171
|
+
// (Only meaningful if the chain verifies in the first place.)
|
|
172
|
+
if (chainValid) {
|
|
173
|
+
const commitTypes = this.commitTypes();
|
|
174
|
+
const chainIntentIds = new Set();
|
|
175
|
+
for (const e of this.cfg.audit.entries()) {
|
|
176
|
+
if (!commitTypes.has(e.event.type))
|
|
177
|
+
continue;
|
|
178
|
+
const id = this.intentIdOf(e.event);
|
|
179
|
+
if (id)
|
|
180
|
+
chainIntentIds.add(id);
|
|
181
|
+
}
|
|
182
|
+
const committedIds = new Set(input.committed.map((c) => c.intent.id));
|
|
183
|
+
for (const c of input.committed) {
|
|
184
|
+
if (!chainIntentIds.has(c.intent.id)) {
|
|
185
|
+
findings.push({
|
|
186
|
+
code: 'UNRECORDED_SPEND', severity: 'critical',
|
|
187
|
+
detail: 'A signed, committed intent has no matching entry in the audit chain — money moved with no record.',
|
|
188
|
+
agentDid: c.intent.agent, mandateId: c.intent.mandateId, intentId: c.intent.id,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
for (const id of chainIntentIds) {
|
|
193
|
+
if (!committedIds.has(id)) {
|
|
194
|
+
findings.push({
|
|
195
|
+
code: 'PHANTOM_ENTRY', severity: 'critical',
|
|
196
|
+
detail: 'A commit entry in the audit chain references an intent with no backing signed object — a record with no provable spend.',
|
|
197
|
+
intentId: id,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// 6. Enforcement: demote every agent provably caught in a security anomaly,
|
|
203
|
+
// once per audit (asymmetric, instant — the ladder's whole purpose).
|
|
204
|
+
const offenders = new Set();
|
|
205
|
+
for (const f of findings) {
|
|
206
|
+
const isSecurity = SECURITY_REASONS.has(f.code) || f.code === 'SPEND_AFTER_REVOCATION' || f.code === 'REPLAY_IN_LEDGER';
|
|
207
|
+
if (isSecurity && f.agentDid)
|
|
208
|
+
offenders.add(f.agentDid);
|
|
209
|
+
}
|
|
210
|
+
const demoted = [];
|
|
211
|
+
if (this.cfg.ladder) {
|
|
212
|
+
for (const agentDid of offenders) {
|
|
213
|
+
this.cfg.ladder.record(agentDid, 'security_anomaly');
|
|
214
|
+
demoted.push(agentDid);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
// 7. Tally, sign the attestation, and anchor the audit-of-the-audit.
|
|
218
|
+
const summary = EMPTY_SUMMARY();
|
|
219
|
+
for (const f of findings)
|
|
220
|
+
summary[f.severity] += 1;
|
|
221
|
+
const clean = summary.violation === 0 && summary.critical === 0;
|
|
222
|
+
const entries = this.cfg.audit.entries();
|
|
223
|
+
const chainHead = entries.length > 0 ? entries[entries.length - 1].hash : GENESIS;
|
|
224
|
+
const attestation = this.signAttestation(chainHead, at, findings);
|
|
225
|
+
this.cfg.oversight?.append({
|
|
226
|
+
type: 'audit.completed',
|
|
227
|
+
auditor: this.cfg.auditorKeys.did,
|
|
228
|
+
chainHead, chainValid, clean,
|
|
229
|
+
findingCount: findings.length,
|
|
230
|
+
summary,
|
|
231
|
+
demoted,
|
|
232
|
+
}, this.now());
|
|
233
|
+
return {
|
|
234
|
+
at, chainValid, clean, findings, summary,
|
|
235
|
+
reconciledMandates: mandates.size,
|
|
236
|
+
reconciledSpends: input.committed.length,
|
|
237
|
+
demoted, attestation,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
signAttestation(chainHead, at, findings) {
|
|
241
|
+
const doc = {
|
|
242
|
+
type: 'KyaAuditAttestation',
|
|
243
|
+
auditor: this.cfg.auditorKeys.did,
|
|
244
|
+
chainHead, at, findings,
|
|
245
|
+
};
|
|
246
|
+
const signature = toBase58(sign(canonicalBytes(doc), this.cfg.auditorKeys.privateKey));
|
|
247
|
+
return { ...doc, signature };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=auditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditor.js","sourceRoot":"","sources":["../src/auditor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* continuous-auditor.ts — the operator surface around the Auditor.
|
|
3
|
+
*
|
|
4
|
+
* The Auditor answers one question per call. An operator (or the CFO inbox)
|
|
5
|
+
* wants the *running* answer: has the fleet ever drifted, how long has it been
|
|
6
|
+
* clean, and what is the tamper-evident history of every attestation it signed?
|
|
7
|
+
*
|
|
8
|
+
* This wraps AuditorAgent into a run-on-demand loop — drive it from a cron, a
|
|
9
|
+
* queue, or a `while` loop — and folds each pass into a running record. The
|
|
10
|
+
* `oversight` AuditLog shared via config anchors every run into a hash chain,
|
|
11
|
+
* so the audit history is itself audited. Each signed attestation is a portable
|
|
12
|
+
* object the human-governance ring can ingest and verify offline.
|
|
13
|
+
*/
|
|
14
|
+
import { type AuditAttestation, type AuditInput, type AuditReport, type AuditorConfig } from './auditor.js';
|
|
15
|
+
export interface AuditHealth {
|
|
16
|
+
runs: number;
|
|
17
|
+
/** Has ANY pass come back non-clean? Monitors latch on this. */
|
|
18
|
+
everDirty: boolean;
|
|
19
|
+
/** Consecutive clean passes ending at the latest run. */
|
|
20
|
+
cleanStreak: number;
|
|
21
|
+
/** Findings in the most recent pass. */
|
|
22
|
+
openFindings: number;
|
|
23
|
+
lastAuditAt?: string;
|
|
24
|
+
lastAttestation?: AuditAttestation;
|
|
25
|
+
}
|
|
26
|
+
export declare class ContinuousAuditor {
|
|
27
|
+
private readonly auditor;
|
|
28
|
+
private readonly reports;
|
|
29
|
+
constructor(cfg: AuditorConfig);
|
|
30
|
+
/** Run one audit pass and fold it into the running record. */
|
|
31
|
+
run(input: AuditInput): Promise<AuditReport>;
|
|
32
|
+
/** Every signed attestation, in run order — the audit-of-record stream. */
|
|
33
|
+
attestations(): AuditAttestation[];
|
|
34
|
+
history(): readonly AuditReport[];
|
|
35
|
+
/** A one-glance operational summary for a dashboard or the CFO inbox. */
|
|
36
|
+
health(): AuditHealth;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=continuous-auditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuous-auditor.d.ts","sourceRoot":"","sources":["../src/continuous-auditor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAgB,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAE1H,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,SAAS,EAAE,OAAO,CAAC;IACnB,yDAAyD;IACzD,WAAW,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,GAAG,EAAE,aAAa;IAI9B,8DAA8D;IACxD,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAMlD,2EAA2E;IAC3E,YAAY,IAAI,gBAAgB,EAAE;IAIlC,OAAO,IAAI,SAAS,WAAW,EAAE;IAIjC,yEAAyE;IACzE,MAAM,IAAI,WAAW;CAetB"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* continuous-auditor.ts — the operator surface around the Auditor.
|
|
3
|
+
*
|
|
4
|
+
* The Auditor answers one question per call. An operator (or the CFO inbox)
|
|
5
|
+
* wants the *running* answer: has the fleet ever drifted, how long has it been
|
|
6
|
+
* clean, and what is the tamper-evident history of every attestation it signed?
|
|
7
|
+
*
|
|
8
|
+
* This wraps AuditorAgent into a run-on-demand loop — drive it from a cron, a
|
|
9
|
+
* queue, or a `while` loop — and folds each pass into a running record. The
|
|
10
|
+
* `oversight` AuditLog shared via config anchors every run into a hash chain,
|
|
11
|
+
* so the audit history is itself audited. Each signed attestation is a portable
|
|
12
|
+
* object the human-governance ring can ingest and verify offline.
|
|
13
|
+
*/
|
|
14
|
+
import { AuditorAgent } from './auditor.js';
|
|
15
|
+
export class ContinuousAuditor {
|
|
16
|
+
auditor;
|
|
17
|
+
reports = [];
|
|
18
|
+
constructor(cfg) {
|
|
19
|
+
this.auditor = new AuditorAgent(cfg);
|
|
20
|
+
}
|
|
21
|
+
/** Run one audit pass and fold it into the running record. */
|
|
22
|
+
async run(input) {
|
|
23
|
+
const report = await this.auditor.audit(input);
|
|
24
|
+
this.reports.push(report);
|
|
25
|
+
return report;
|
|
26
|
+
}
|
|
27
|
+
/** Every signed attestation, in run order — the audit-of-record stream. */
|
|
28
|
+
attestations() {
|
|
29
|
+
return this.reports.map((r) => r.attestation);
|
|
30
|
+
}
|
|
31
|
+
history() {
|
|
32
|
+
return this.reports;
|
|
33
|
+
}
|
|
34
|
+
/** A one-glance operational summary for a dashboard or the CFO inbox. */
|
|
35
|
+
health() {
|
|
36
|
+
let cleanStreak = 0;
|
|
37
|
+
for (let i = this.reports.length - 1; i >= 0; i--) {
|
|
38
|
+
if (!this.reports[i].clean)
|
|
39
|
+
break;
|
|
40
|
+
cleanStreak += 1;
|
|
41
|
+
}
|
|
42
|
+
const last = this.reports[this.reports.length - 1];
|
|
43
|
+
return {
|
|
44
|
+
runs: this.reports.length,
|
|
45
|
+
everDirty: this.reports.some((r) => !r.clean),
|
|
46
|
+
cleanStreak,
|
|
47
|
+
openFindings: last ? last.findings.length : 0,
|
|
48
|
+
...(last ? { lastAuditAt: last.at, lastAttestation: last.attestation } : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=continuous-auditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"continuous-auditor.js","sourceRoot":"","sources":["../src/continuous-auditor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,YAAY,EAAgF,MAAM,cAAc,CAAC;AAc1H,MAAM,OAAO,iBAAiB;IACX,OAAO,CAAe;IACtB,OAAO,GAAkB,EAAE,CAAC;IAE7C,YAAY,GAAkB;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;IACvC,CAAC;IAED,8DAA8D;IAC9D,KAAK,CAAC,GAAG,CAAC,KAAiB;QACzB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,2EAA2E;IAC3E,YAAY;QACV,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,yEAAyE;IACzE,MAAM;QACJ,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK;gBAAE,MAAM;YACnC,WAAW,IAAI,CAAC,CAAC;QACnB,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YACzB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAC7C,WAAW;YACX,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC7C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC7E,CAAC;IACJ,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kyaki/agents — L2 Agent Runtime.
|
|
3
|
+
*
|
|
4
|
+
* Two spenders, a watcher, and a steward:
|
|
5
|
+
* ProcurerAgent — sources compliant vendors, spends outward, proves savings.
|
|
6
|
+
* Treasurer — manages the balance sheet: obligations, FX sourcing, sweeps.
|
|
7
|
+
* AuditorAgent — spends nothing; proves the fleet stayed inside authority
|
|
8
|
+
* and signs a verifiable audit-of-record.
|
|
9
|
+
* Steward — acts on the PRINCIPAL's key: issues mandates from policy and
|
|
10
|
+
* revokes them when the Auditor proves an agent misbehaved.
|
|
11
|
+
*/
|
|
12
|
+
export type { ApprovalRequest, Market, OutcomeStatus, ProcurementNeed, ProcurementOutcome, SkippedOffer, VendorOffer } from './types.js';
|
|
13
|
+
export { MockMarket } from './market.js';
|
|
14
|
+
export { ApprovalInbox, signApproval, verifyApproval, type SignedApproval } from './approvals.js';
|
|
15
|
+
export { ProcurerAgent, type ProcurerConfig } from './procurer.js';
|
|
16
|
+
export { Treasurer, StaticFX, TreasuryApprovalInbox, type Account, type AccountType, type ActionKind, type ActionStatus, type CashPosition, type FXProvider, type Obligation, type PendingMovement, type MovementStatus, type TreasurerConfig, type TreasuryAction, } from './treasury.js';
|
|
17
|
+
export { AuditorAgent, verifyAuditAttestation, type AuditAttestation, type AuditInput, type AuditReport, type AuditorConfig, type CommittedSpend, type Finding, type RevocationRecord, type Severity, } from './auditor.js';
|
|
18
|
+
export { ContinuousAuditor, type AuditHealth } from './continuous-auditor.js';
|
|
19
|
+
export { Steward, verifyGovernanceAttestation, type AuthorityAction, type AuthorityActionKind, type GovernanceAttestation, type StewardConfig, } from './steward.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzI,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EACL,SAAS,EAAE,QAAQ,EAAE,qBAAqB,EAC1C,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAClE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EACzE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,GAC/D,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EAAE,sBAAsB,EACpC,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAC5E,KAAK,cAAc,EAAE,KAAK,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,GACxE,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EACL,OAAO,EAAE,2BAA2B,EACpC,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,KAAK,aAAa,GAC/F,MAAM,cAAc,CAAC"}
|