@uuaid/agent-commons 0.0.0 → 0.2.0-alpha.4
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/CONFORMANCE.md +26 -0
- package/LICENSE +201 -0
- package/NOTICE +22 -0
- package/PROVENANCE.json +24 -0
- package/README.md +404 -5
- package/bin/agent-commons.mjs +76 -0
- package/examples/Dockerfile +12 -0
- package/examples/agent.mjs +17 -0
- package/examples/global-policy.json +9 -0
- package/examples/run-cohort.mjs +68 -0
- package/package.json +31 -8
- package/profiles/agentnet.chat.json +11 -0
- package/profiles/local.json +11 -0
- package/profiles/zilligon.com.json +11 -0
- package/profiles/zilligons.com.json +11 -0
- package/src/carrier.mjs +84 -0
- package/src/channels.d.mts +75 -0
- package/src/channels.mjs +158 -0
- package/src/cohort.mjs +61 -0
- package/src/collaboration.mjs +875 -0
- package/src/config.mjs +40 -0
- package/src/continuity.d.mts +24 -0
- package/src/continuity.mjs +601 -0
- package/src/governance-scope.d.mts +46 -0
- package/src/governance-scope.mjs +139 -0
- package/src/governance.mjs +355 -0
- package/src/index.d.ts +111 -0
- package/src/index.mjs +15 -0
- package/src/loop.mjs +71 -0
- package/src/offline.d.mts +7 -0
- package/src/offline.mjs +29 -0
- package/src/pillar.mjs +59 -0
- package/src/profiles.d.mts +12 -0
- package/src/profiles.mjs +92 -0
- package/src/relay/auth.mjs +294 -0
- package/src/relay/board.mjs +223 -0
- package/src/relay/claims.mjs +25 -0
- package/src/relay/cli.mjs +49 -0
- package/src/relay/client.mjs +437 -0
- package/src/relay/docs/reconnect-v1.md +27 -0
- package/src/relay/docs/working-rules-v1.md +42 -0
- package/src/relay/enroll.mjs +232 -0
- package/src/relay/export-cli.mjs +47 -0
- package/src/relay/governance.mjs +1328 -0
- package/src/relay/mailbox.mjs +103 -0
- package/src/relay/records.mjs +146 -0
- package/src/relay/render.mjs +38 -0
- package/src/relay/roster.mjs +134 -0
- package/src/relay/routes.mjs +87 -0
- package/src/relay/schema.mjs +1081 -0
- package/src/relay/seed.mjs +89 -0
- package/src/relay/serve.mjs +116 -0
- package/src/relay/server.mjs +633 -0
- package/src/relay/signing.mjs +693 -0
- package/src/relay/test-mode.mjs +73 -0
- package/src/runtime.mjs +359 -0
- package/src/spaces/manifest.mjs +245 -0
- package/src/spaces/pillar-group.mjs +12 -0
- package/src/spaces/policy.mjs +229 -0
- package/src/spaces/store.mjs +325 -0
- package/src/store.mjs +73 -0
- package/src/transport.d.mts +76 -0
- package/src/transport.mjs +267 -0
- package/src/trust.mjs +104 -0
- package/src/uuaid-namespace.d.mts +6 -0
- package/src/uuaid-namespace.mjs +48 -0
- package/src/vendor/pillar/blob/blob.mjs +508 -0
- package/src/vendor/pillar/crypto/e2e.mjs +97 -0
- package/src/vendor/pillar/groups-v2.mjs +1108 -0
- package/src/vendor/pillar/groups.mjs +175 -0
- package/src/vendor/pillar/identity/jcs.mjs +34 -0
- package/src/vendor/pillar/identity/keychain.mjs +241 -0
- package/src/vendor/pillar/identity/tier.mjs +130 -0
- package/src/vendor/pillar/net/carrier-client.mjs +219 -0
- package/src/vendor/pillar/net/delegation.mjs +209 -0
- package/src/vendor/pillar/net/envelope.mjs +258 -0
- package/src/vendor/pillar/net/refusals.mjs +129 -0
- package/src/vendor/pillar/net/seed-tier.mjs +185 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classifies an operation into one of three tiers:
|
|
3
|
+
* - Tier 1: Local peer messaging (offline, key-derived identities, no registry/principal checks)
|
|
4
|
+
* - Tier 2: Default local profile evolution (offline, commons:evolve, produces advisory approval)
|
|
5
|
+
* - Tier 3: Principal-governed institutional operations (strict opt-in, mandatory action-time verifier)
|
|
6
|
+
*/
|
|
7
|
+
export function classifyOperationTier(operation, options = {}) {
|
|
8
|
+
const { scope, policy } = options;
|
|
9
|
+
|
|
10
|
+
// Tier 1: Local peer messaging operations
|
|
11
|
+
if (
|
|
12
|
+
[
|
|
13
|
+
"send",
|
|
14
|
+
"receive",
|
|
15
|
+
"receiveInternal",
|
|
16
|
+
"flush",
|
|
17
|
+
"flushInternal",
|
|
18
|
+
"broadcast",
|
|
19
|
+
"poll"
|
|
20
|
+
].includes(operation)
|
|
21
|
+
) {
|
|
22
|
+
return "tier1-messaging";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Tier 3: Explicit global scope, global policy mode, explicit principal-required mode, or standards items
|
|
26
|
+
if (
|
|
27
|
+
scope === "global" ||
|
|
28
|
+
policy?.mode === "global" ||
|
|
29
|
+
policy?.governanceMode === "principal-required" ||
|
|
30
|
+
operation === "standards-work"
|
|
31
|
+
) {
|
|
32
|
+
return "tier3-principal-governed";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Tier 2: Local profile evolution under default mode
|
|
36
|
+
if (["propose", "vote", "apply", "applyInternal"].includes(operation)) {
|
|
37
|
+
return "tier2-default-local-evolution";
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Fail-closed default for unknown operations
|
|
41
|
+
return "tier3-principal-governed";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enforces action-time principal mapping and status verification for Tier 3 governance actions.
|
|
46
|
+
* Missing mapping fails with PRINCIPAL_MAPPING_REQUIRED.
|
|
47
|
+
* Verifier failure or errors fail with STATUS_VERIFIER_UNAVAILABLE.
|
|
48
|
+
* Superseded status fails with PRINCIPAL_SUPERSEDED.
|
|
49
|
+
* Suspended/revoked/expired/not-found fail with PRINCIPAL_STATUS_DENIED.
|
|
50
|
+
* Strict no-fallback rule: governed refusals never degrade to Tier 2 local evolution.
|
|
51
|
+
*/
|
|
52
|
+
export async function verifyPrincipalGovernance(uuaid, verifier, policy) {
|
|
53
|
+
const principalId = policy?.principals?.[uuaid];
|
|
54
|
+
if (!principalId) {
|
|
55
|
+
const err = new Error(`Principal mapping required for ${uuaid}`);
|
|
56
|
+
err.code = "PRINCIPAL_MAPPING_REQUIRED";
|
|
57
|
+
throw err;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!verifier || typeof verifier.checkStatus !== "function") {
|
|
61
|
+
const err = new Error("Status verifier unavailable: no verifier configured");
|
|
62
|
+
err.code = "STATUS_VERIFIER_UNAVAILABLE";
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let result;
|
|
67
|
+
try {
|
|
68
|
+
result = await verifier.checkStatus(principalId);
|
|
69
|
+
} catch (cause) {
|
|
70
|
+
const err = new Error(`Status verifier unavailable: ${cause.message}`);
|
|
71
|
+
err.code = "STATUS_VERIFIER_UNAVAILABLE";
|
|
72
|
+
err.cause = cause;
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!result || typeof result !== "object" || !result.status) {
|
|
77
|
+
const err = new Error("Status verifier returned invalid result");
|
|
78
|
+
err.code = "STATUS_VERIFIER_UNAVAILABLE";
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (result.status === "superseded") {
|
|
83
|
+
const err = new Error(`Principal ${principalId} is superseded`);
|
|
84
|
+
err.code = "PRINCIPAL_SUPERSEDED";
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (result.status !== "active") {
|
|
89
|
+
const err = new Error(`Principal ${principalId} status denied: ${result.status}`);
|
|
90
|
+
err.code = "PRINCIPAL_STATUS_DENIED";
|
|
91
|
+
err.status = result.status;
|
|
92
|
+
throw err;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
principalId,
|
|
97
|
+
status: "active",
|
|
98
|
+
checkedAt: result.checkedAt ?? Date.now()
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* In-memory test fixture implementing PrincipalStatusVerifier for offline tests.
|
|
104
|
+
*/
|
|
105
|
+
export class MockPrincipalStatusVerifier {
|
|
106
|
+
#statuses = new Map();
|
|
107
|
+
#errors = new Map();
|
|
108
|
+
|
|
109
|
+
constructor(initialStatuses = {}) {
|
|
110
|
+
if (initialStatuses instanceof Map) {
|
|
111
|
+
for (const [k, v] of initialStatuses) {
|
|
112
|
+
this.#statuses.set(k, v);
|
|
113
|
+
}
|
|
114
|
+
} else if (typeof initialStatuses === "object" && initialStatuses !== null) {
|
|
115
|
+
for (const [k, v] of Object.entries(initialStatuses)) {
|
|
116
|
+
this.#statuses.set(k, v);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setStatus(principalId, status) {
|
|
122
|
+
this.#statuses.set(principalId, status);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
setThrows(principalId, error) {
|
|
126
|
+
this.#errors.set(principalId, error);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async checkStatus(principalId) {
|
|
130
|
+
if (this.#errors.has(principalId)) {
|
|
131
|
+
throw this.#errors.get(principalId);
|
|
132
|
+
}
|
|
133
|
+
const status = this.#statuses.get(principalId) ?? "not-found";
|
|
134
|
+
return {
|
|
135
|
+
status,
|
|
136
|
+
checkedAt: Date.now()
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { assertJSON, BASE_PROTOCOL, digest } from "./profiles.mjs";
|
|
2
|
+
import { jcs, Keychain } from "./pillar.mjs";
|
|
3
|
+
import { SELF_CERTIFYING_AGENT_UUAID } from "./uuaid-namespace.mjs";
|
|
4
|
+
|
|
5
|
+
// This module deliberately performs no network calls and executes no changes.
|
|
6
|
+
// Operators must inject verifiers backed by actual identity/evidence authorities.
|
|
7
|
+
export class GovernanceError extends Error {
|
|
8
|
+
constructor(code, message = code) { super(message); this.name = "GovernanceError"; this.code = code; }
|
|
9
|
+
}
|
|
10
|
+
const fail = (code, message) => { throw new GovernanceError(code, message); };
|
|
11
|
+
const text = value => typeof value === "string" && value.length > 0 && value.length <= 256;
|
|
12
|
+
const hash = value => typeof value === "string" && /^[0-9a-f]{64}$/.test(value);
|
|
13
|
+
const timestamp = value => typeof value === "string" ? Date.parse(value) : NaN;
|
|
14
|
+
const clone = value => structuredClone(value);
|
|
15
|
+
const DOCUMENT_KINDS = ["governance-contribution", "governance-evidence-review", "governance-proposal", "governance-vote"];
|
|
16
|
+
export function verifyGovernanceDocument(document) {
|
|
17
|
+
assertJSON(document);
|
|
18
|
+
if (!document || Object.keys(document).some(k => !["v", "id", "kind", "issuer", "publicKey", "createdAt", "payload", "signature"].includes(k)) ||
|
|
19
|
+
Buffer.byteLength(JSON.stringify(document)) > ACTION_MANIFEST.ceilings.bytes) fail("INVALID_DOCUMENT");
|
|
20
|
+
const { signature, ...body } = document;
|
|
21
|
+
if (body.v !== BASE_PROTOCOL || !DOCUMENT_KINDS.includes(body.kind) ||
|
|
22
|
+
typeof body.id !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(body.id) ||
|
|
23
|
+
typeof body.issuer !== "string" || !SELF_CERTIFYING_AGENT_UUAID.test(body.issuer) ||
|
|
24
|
+
!hash(body.publicKey) || typeof signature !== "string" || !/^[0-9a-f]{128}$/.test(signature)) fail("INVALID_DOCUMENT");
|
|
25
|
+
if (Keychain.localIdFromKey(Buffer.from(body.publicKey, "hex")) !== body.issuer.split(":")[3] ||
|
|
26
|
+
!Keychain.verifyDetached(body.publicKey, Buffer.from(jcs(body)), Buffer.from(signature, "hex"))) fail("INVALID_SIGNATURE");
|
|
27
|
+
return body;
|
|
28
|
+
}
|
|
29
|
+
function freeze(value) {
|
|
30
|
+
if (value && typeof value === "object") { Object.values(value).forEach(freeze); Object.freeze(value); }
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
export const CLAIM_TYPES = freeze(["AAIU", "AIOU", "Zilligon"]);
|
|
34
|
+
export const ACTION_MANIFEST = freeze({
|
|
35
|
+
version: 1,
|
|
36
|
+
actions: {
|
|
37
|
+
"inspect": { scopes: ["local", "global"], permission: "observe" },
|
|
38
|
+
"submit-evidence": { scopes: ["local", "global"], permission: "contribute" },
|
|
39
|
+
"review-evidence": { scopes: ["local", "global"], permission: "review-evidence" },
|
|
40
|
+
"propose-alias": { scopes: ["local", "global"], permission: "propose" },
|
|
41
|
+
"review-proposal": { scopes: ["local", "global"], permission: "review" },
|
|
42
|
+
},
|
|
43
|
+
ceilings: { calls: 100, bytes: 32000, durationMs: 3600000 },
|
|
44
|
+
execution: "advisory-only",
|
|
45
|
+
globalRatification: false,
|
|
46
|
+
selfModification: false,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/** A one-run guard, not a scheduler or an execution capability. */
|
|
50
|
+
export function createActionBudget({ scope = "local", maxCalls = 16, maxBytes = 8000, durationMs = 60000, clock = Date.now } = {}) {
|
|
51
|
+
context({ scope, namespace: "budget" });
|
|
52
|
+
const ceilings = ACTION_MANIFEST.ceilings;
|
|
53
|
+
for (const [value, ceiling] of [[maxCalls, ceilings.calls], [maxBytes, ceilings.bytes], [durationMs, ceilings.durationMs]]) {
|
|
54
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > ceiling) fail("INVALID_BUDGET");
|
|
55
|
+
}
|
|
56
|
+
if (typeof clock !== "function") fail("INVALID_CLOCK");
|
|
57
|
+
const start = clock();
|
|
58
|
+
if (!Number.isSafeInteger(start)) fail("INVALID_CLOCK");
|
|
59
|
+
let calls = 0, bytes = 0, last = start;
|
|
60
|
+
return freeze({
|
|
61
|
+
consume(request) {
|
|
62
|
+
const now = clock();
|
|
63
|
+
if (!Number.isSafeInteger(now) || now < last) fail("INVALID_CLOCK");
|
|
64
|
+
last = now;
|
|
65
|
+
if (now - start >= durationMs) fail("BUDGET_EXPIRED");
|
|
66
|
+
if (!request || Object.keys(request).some(k => !["action", "scope", "payload"].includes(k))) fail("INVALID_ACTION");
|
|
67
|
+
const definition = Object.hasOwn(ACTION_MANIFEST.actions, request.action) && ACTION_MANIFEST.actions[request.action];
|
|
68
|
+
if (!definition || request.scope !== scope || !definition.scopes.includes(scope)) fail("ACTION_FORBIDDEN");
|
|
69
|
+
let encoded;
|
|
70
|
+
try { assertJSON(request); encoded = JSON.stringify(request); } catch { fail("INVALID_ACTION"); }
|
|
71
|
+
const size = Buffer.byteLength(encoded);
|
|
72
|
+
if (calls + 1 > maxCalls || bytes + size > maxBytes) fail("BUDGET_EXCEEDED");
|
|
73
|
+
calls++; bytes += size;
|
|
74
|
+
return { calls, bytes, permission: definition.permission, executionAllowed: false };
|
|
75
|
+
},
|
|
76
|
+
status() { return { calls, bytes, maxCalls, maxBytes, scope, executionAllowed: false }; },
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function context(value) {
|
|
81
|
+
if (!value || !["local", "global"].includes(value.scope) || !text(value.namespace)) fail("INVALID_CONTEXT");
|
|
82
|
+
return { scope: value.scope, namespace: value.namespace };
|
|
83
|
+
}
|
|
84
|
+
const sameContext = (a, b) => a.scope === b.scope && a.namespace === b.namespace;
|
|
85
|
+
const defaults = {
|
|
86
|
+
halfLifeMs: 30 * 86400000, freshnessMs: 300000, documentMaxAgeMs: 86400000,
|
|
87
|
+
evidenceMaxAgeMs: 90 * 86400000, quorum: 2, maxRecords: 1000,
|
|
88
|
+
requiredGlobalClaims: [], agents: {}, claimIssuers: {}, credentialIssuers: [],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Signed, bounded, in-memory oversight. All data is advisory: even a locally
|
|
93
|
+
* approved proposal is never installed here. Persist signed inputs externally.
|
|
94
|
+
*/
|
|
95
|
+
export class PeerGovernance {
|
|
96
|
+
#policy; #adapters; #clock; #contributions = new Map(); #proposals = new Map();
|
|
97
|
+
#documents = new Map(); #tail = Promise.resolve(); #lastNow = -Infinity;
|
|
98
|
+
constructor({ policy = {}, adapters = {}, clock = Date.now } = {}) {
|
|
99
|
+
this.#policy = freeze(clone({ ...defaults, ...policy }));
|
|
100
|
+
this.#adapters = { ...adapters };
|
|
101
|
+
this.#clock = clock;
|
|
102
|
+
for (const key of ["halfLifeMs", "freshnessMs", "documentMaxAgeMs", "evidenceMaxAgeMs", "maxRecords"]) {
|
|
103
|
+
if (!Number.isSafeInteger(this.#policy[key]) || this.#policy[key] < 1) fail("INVALID_POLICY");
|
|
104
|
+
}
|
|
105
|
+
if (!Number.isSafeInteger(this.#policy.quorum) || this.#policy.quorum < 2 || this.#policy.quorum > 32 ||
|
|
106
|
+
this.#policy.maxRecords > 10000 || !Array.isArray(this.#policy.requiredGlobalClaims) ||
|
|
107
|
+
this.#policy.requiredGlobalClaims.some(type => !CLAIM_TYPES.includes(type)) ||
|
|
108
|
+
new Set(this.#policy.requiredGlobalClaims).size !== this.#policy.requiredGlobalClaims.length ||
|
|
109
|
+
!Array.isArray(this.#policy.credentialIssuers) || typeof clock !== "function") fail("INVALID_POLICY");
|
|
110
|
+
this.#now();
|
|
111
|
+
}
|
|
112
|
+
#now() {
|
|
113
|
+
const now = this.#clock();
|
|
114
|
+
if (!Number.isSafeInteger(now) || now < this.#lastNow) fail("INVALID_CLOCK");
|
|
115
|
+
this.#lastNow = now;
|
|
116
|
+
return now;
|
|
117
|
+
}
|
|
118
|
+
#binding(subject, publicKey) {
|
|
119
|
+
const binding = Object.hasOwn(this.#policy.agents, subject) && this.#policy.agents[subject];
|
|
120
|
+
if (!binding || binding.kind !== "agent" || binding.publicKey !== publicKey ||
|
|
121
|
+
!hash(publicKey) || !text(binding.controllerId) || !Array.isArray(binding.affiliations) ||
|
|
122
|
+
binding.affiliations.some(a => !text(a)) || !Array.isArray(binding.capabilities) ||
|
|
123
|
+
// A block on any binding of this key blocks the key, under every spelling.
|
|
124
|
+
Object.values(this.#policy.agents).some(a => a?.publicKey === publicKey && a.blocked === true)) fail("NOT_ADMITTED");
|
|
125
|
+
return binding;
|
|
126
|
+
}
|
|
127
|
+
async #adapter(name, request) {
|
|
128
|
+
if (typeof this.#adapters[name] !== "function") fail("VERIFIER_UNAVAILABLE", `${name} must be injected`);
|
|
129
|
+
try { return await this.#adapters[name](freeze(clone(request))); }
|
|
130
|
+
catch { fail("VERIFIER_UNAVAILABLE", `${name} could not verify`); }
|
|
131
|
+
}
|
|
132
|
+
#current(verdict, request) {
|
|
133
|
+
const now = this.#now();
|
|
134
|
+
return verdict && verdict.subject === request.subject && verdict.publicKey === request.publicKey &&
|
|
135
|
+
verdict.signatureValid === true && verdict.revoked === false && verdict.notExpired === true &&
|
|
136
|
+
Number.isFinite(timestamp(verdict.expiresAt)) && timestamp(verdict.expiresAt) > now &&
|
|
137
|
+
Number.isFinite(timestamp(verdict.checkedAt)) && timestamp(verdict.checkedAt) <= now &&
|
|
138
|
+
now - timestamp(verdict.checkedAt) <= this.#policy.freshnessMs;
|
|
139
|
+
}
|
|
140
|
+
async #authorize(subject, publicKey, capability, ctx) {
|
|
141
|
+
ctx = context(ctx);
|
|
142
|
+
const binding = this.#binding(subject, publicKey);
|
|
143
|
+
if (!binding.capabilities.includes(capability)) fail("CAPABILITY_DENIED");
|
|
144
|
+
const verdict = await this.#adapter("authorize", { subject, publicKey, capability, ...ctx });
|
|
145
|
+
if (verdict?.authorized !== true || verdict.subject !== subject || verdict.publicKey !== publicKey ||
|
|
146
|
+
verdict.capability !== capability || !sameContext(verdict, ctx)) fail("AUTHORIZATION_DENIED");
|
|
147
|
+
if (ctx.scope === "global" || binding.credentialId !== undefined) {
|
|
148
|
+
if (!text(binding.credentialId)) fail("CREDENTIAL_REQUIRED");
|
|
149
|
+
const request = { subject, publicKey, credentialId: binding.credentialId, ...ctx };
|
|
150
|
+
const credential = await this.#adapter("verifyCredential", request);
|
|
151
|
+
if (!this.#current(credential, request) || credential.valid !== true ||
|
|
152
|
+
credential.credentialId !== binding.credentialId ||
|
|
153
|
+
!sameContext(credential, ctx) ||
|
|
154
|
+
!this.#policy.credentialIssuers.includes(credential.issuer)) fail("CREDENTIAL_INVALID");
|
|
155
|
+
}
|
|
156
|
+
if (ctx.scope === "global") await this.checkClaims(subject, publicKey, ctx, this.#policy.requiredGlobalClaims);
|
|
157
|
+
return binding;
|
|
158
|
+
}
|
|
159
|
+
/** Badges, display names, domains and model/provider labels are never consulted. */
|
|
160
|
+
async checkClaims(subject, publicKey, ctx, required = CLAIM_TYPES) {
|
|
161
|
+
ctx = context(ctx);
|
|
162
|
+
const binding = this.#binding(subject, publicKey);
|
|
163
|
+
if (!Array.isArray(required) || required.some(type => !CLAIM_TYPES.includes(type))) fail("UNKNOWN_CLAIM");
|
|
164
|
+
const verified = [];
|
|
165
|
+
for (const type of required) {
|
|
166
|
+
const claimId = binding.claims?.[type];
|
|
167
|
+
const issuers = this.#policy.claimIssuers[type];
|
|
168
|
+
if (!text(claimId) || !Array.isArray(issuers) || !issuers.length) fail("CLAIM_UNVERIFIED");
|
|
169
|
+
const request = { subject, publicKey, type, claimId, ...ctx };
|
|
170
|
+
const verdict = await this.#adapter("verifyClaim", request);
|
|
171
|
+
if (!this.#current(verdict, request) || verdict.verified !== true || verdict.type !== type ||
|
|
172
|
+
verdict.claimId !== claimId || !sameContext(verdict, ctx) || !issuers.includes(verdict.issuer)) fail("CLAIM_UNVERIFIED");
|
|
173
|
+
verified.push({ type, claimId, issuer: verdict.issuer, expiresAt: verdict.expiresAt });
|
|
174
|
+
}
|
|
175
|
+
return verified;
|
|
176
|
+
}
|
|
177
|
+
#independent(a, b) {
|
|
178
|
+
if (a === b) fail("SELF_REVIEW");
|
|
179
|
+
const x = this.#policy.agents[a], y = this.#policy.agents[b];
|
|
180
|
+
if (!x || !y || x.publicKey === y.publicKey || x.controllerId === y.controllerId ||
|
|
181
|
+
x.affiliations.some(group => y.affiliations.includes(group)) ||
|
|
182
|
+
x.conflicts?.includes(b) || y.conflicts?.includes(a)) fail("REVIEWER_CONFLICT");
|
|
183
|
+
}
|
|
184
|
+
async #evidence(record) {
|
|
185
|
+
const verdict = await this.#adapter("verifyEvidence", record);
|
|
186
|
+
const now = this.#now(), observed = timestamp(verdict?.observedAt);
|
|
187
|
+
if (verdict?.verified !== true || verdict.subject !== record.subject ||
|
|
188
|
+
verdict.evidenceHash !== record.evidenceHash || !sameContext(verdict, record) ||
|
|
189
|
+
verdict.outcome !== "pass" || !Number.isFinite(observed) || observed > now ||
|
|
190
|
+
now - observed > this.#policy.evidenceMaxAgeMs ||
|
|
191
|
+
!Number.isFinite(verdict.quality) || verdict.quality <= 0 || verdict.quality > 1) fail("EVIDENCE_INVALID");
|
|
192
|
+
return { observedAt: verdict.observedAt, quality: verdict.quality };
|
|
193
|
+
}
|
|
194
|
+
async #validReviews(record, capability) {
|
|
195
|
+
const valid = [];
|
|
196
|
+
for (const review of record.reviews) {
|
|
197
|
+
try {
|
|
198
|
+
await this.#authorize(review.subject, review.publicKey, capability, record);
|
|
199
|
+
this.#independent(record.subject, review.subject);
|
|
200
|
+
valid.forEach(peer => this.#independent(peer.subject, review.subject));
|
|
201
|
+
valid.push(review);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
if (!(error instanceof GovernanceError)) throw error;
|
|
204
|
+
// A revoked, conflicted or unavailable peer cannot supply credibility.
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return { approvals: valid.filter(r => r.approve).map(r => r.subject), veto: valid.some(r => !r.approve) };
|
|
208
|
+
}
|
|
209
|
+
async credibility(subject, ctx) {
|
|
210
|
+
ctx = context(ctx);
|
|
211
|
+
let score = 0, accepted = 0;
|
|
212
|
+
const evidence = [];
|
|
213
|
+
for (const record of this.#contributions.values()) {
|
|
214
|
+
if (record.subject !== subject || !sameContext(record, ctx)) continue;
|
|
215
|
+
try {
|
|
216
|
+
await this.#authorize(subject, record.publicKey, "commons:contribute", ctx);
|
|
217
|
+
const measured = await this.#evidence(record);
|
|
218
|
+
const reviews = await this.#validReviews(record, "commons:review-evidence");
|
|
219
|
+
if (reviews.veto || reviews.approvals.length < this.#policy.quorum) continue;
|
|
220
|
+
// Use the earlier verified observation, never an adapter refresh time.
|
|
221
|
+
const observed = Math.min(timestamp(record.observedAt), timestamp(measured.observedAt));
|
|
222
|
+
if (this.#now() - observed > this.#policy.evidenceMaxAgeMs) continue;
|
|
223
|
+
const weight = Math.min(record.quality, measured.quality) * 2 ** (-(this.#now() - observed) / this.#policy.halfLifeMs);
|
|
224
|
+
score += weight; accepted++;
|
|
225
|
+
evidence.push({ id: record.id, weight, reviewers: reviews.approvals });
|
|
226
|
+
} catch (error) { if (!(error instanceof GovernanceError)) throw error; }
|
|
227
|
+
}
|
|
228
|
+
score = Math.min(100, score);
|
|
229
|
+
const tier = score >= 6 ? "steward" : score >= 3 ? "established" : score >= 1 ? "contributor" : "observer";
|
|
230
|
+
return { subject, ...ctx, score, accepted, tier, evidence, certified: false };
|
|
231
|
+
}
|
|
232
|
+
async permission(subject, publicKey, action, ctx) {
|
|
233
|
+
ctx = context(ctx);
|
|
234
|
+
const capabilities = { observe: "commons:observe", contribute: "commons:contribute",
|
|
235
|
+
"review-evidence": "commons:review-evidence", propose: "commons:evolve", review: "commons:review" };
|
|
236
|
+
if (!Object.hasOwn(capabilities, action)) fail("ACTION_FORBIDDEN");
|
|
237
|
+
await this.#authorize(subject, publicKey, capabilities[action], ctx);
|
|
238
|
+
const credibility = await this.credibility(subject, ctx);
|
|
239
|
+
const minimum = action === "propose" ? (ctx.scope === "local" ? 1 : 3) :
|
|
240
|
+
action === "review" ? (ctx.scope === "local" ? 3 : 6) : 0;
|
|
241
|
+
return { allowed: credibility.score >= minimum, minimum, ...credibility, action,
|
|
242
|
+
executionAllowed: false, ratified: false };
|
|
243
|
+
}
|
|
244
|
+
apply(document) {
|
|
245
|
+
// Snapshot before queuing: a caller cannot mutate a waiting signed input.
|
|
246
|
+
const snapshot = clone(document);
|
|
247
|
+
const next = this.#tail.then(() => this.#apply(snapshot));
|
|
248
|
+
this.#tail = next.catch(() => {});
|
|
249
|
+
return next;
|
|
250
|
+
}
|
|
251
|
+
async #apply(document) {
|
|
252
|
+
const body = verifyGovernanceDocument(document);
|
|
253
|
+
const now = this.#now(), created = timestamp(body.createdAt);
|
|
254
|
+
if (!Number.isFinite(created) || created > now || now - created > this.#policy.documentMaxAgeMs) fail("STALE_DOCUMENT");
|
|
255
|
+
if (this.#documents.has(document.id)) {
|
|
256
|
+
if (this.#documents.get(document.id) !== digest(document)) fail("DOCUMENT_CONFLICT");
|
|
257
|
+
return { duplicate: true };
|
|
258
|
+
}
|
|
259
|
+
if (this.#documents.size >= this.#policy.maxRecords) fail("RECORD_LIMIT");
|
|
260
|
+
const payload = body.payload;
|
|
261
|
+
const ctx = context(payload);
|
|
262
|
+
const fields = {
|
|
263
|
+
"governance-contribution": ["scope", "namespace", "evidenceHash"],
|
|
264
|
+
"governance-evidence-review": ["scope", "namespace", "contributionId", "evidenceHash", "approve", "rationale"],
|
|
265
|
+
"governance-vote": ["scope", "namespace", "proposalId", "evidenceHash", "approve", "rationale"],
|
|
266
|
+
};
|
|
267
|
+
if (fields[body.kind] && Object.keys(payload).some(k => !fields[body.kind].includes(k))) fail("INVALID_PAYLOAD");
|
|
268
|
+
let result;
|
|
269
|
+
if (body.kind === "governance-contribution") {
|
|
270
|
+
await this.#authorize(body.issuer, body.publicKey, "commons:contribute", ctx);
|
|
271
|
+
if (!hash(payload.evidenceHash)) fail("EVIDENCE_INVALID");
|
|
272
|
+
if ([...this.#contributions.values()].some(r => sameContext(r, ctx) && r.evidenceHash === payload.evidenceHash)) fail("EVIDENCE_REPLAY");
|
|
273
|
+
const record = { id: document.id, subject: body.issuer, publicKey: body.publicKey, ...ctx,
|
|
274
|
+
evidenceHash: payload.evidenceHash, reviews: [] };
|
|
275
|
+
const measured = await this.#evidence(record);
|
|
276
|
+
this.#contributions.set(record.id, { ...record, ...measured });
|
|
277
|
+
result = { id: record.id, status: "awaiting-independent-review", ratified: false };
|
|
278
|
+
} else if (body.kind === "governance-evidence-review") {
|
|
279
|
+
const record = this.#contributions.get(payload.contributionId);
|
|
280
|
+
if (!record || !sameContext(record, ctx)) fail("UNKNOWN_CONTRIBUTION");
|
|
281
|
+
await this.#authorize(body.issuer, body.publicKey, "commons:review-evidence", ctx);
|
|
282
|
+
await this.#authorize(record.subject, record.publicKey, "commons:contribute", ctx);
|
|
283
|
+
this.#reviewEligibility(record, body, payload);
|
|
284
|
+
if (payload.approve) await this.#evidence(record);
|
|
285
|
+
record.reviews.push(this.#review(body, payload));
|
|
286
|
+
result = { id: record.id, status: "review-recorded", ratified: false };
|
|
287
|
+
} else if (body.kind === "governance-proposal") {
|
|
288
|
+
const permission = await this.permission(body.issuer, body.publicKey, "propose", ctx);
|
|
289
|
+
if (!permission.allowed) fail("TIER_DENIED");
|
|
290
|
+
// The only proposed change is an exact phrase alias in immutable data.
|
|
291
|
+
// No executable patch, permission/quorum mutation, or signing changes.
|
|
292
|
+
if (Object.keys(payload).some(k => !["scope", "namespace", "change", "parentHash", "candidateHash", "rollbackHash", "phrase", "evidenceHash"].includes(k)) ||
|
|
293
|
+
payload.change !== "profile-alias" || !hash(payload.parentHash) ||
|
|
294
|
+
!hash(payload.candidateHash) || payload.parentHash === payload.candidateHash ||
|
|
295
|
+
payload.rollbackHash !== payload.parentHash || typeof payload.phrase !== "string" ||
|
|
296
|
+
!/^[A-Za-z][A-Za-z ]{7,79}$/.test(payload.phrase) || payload.phrase !== payload.phrase.trim() ||
|
|
297
|
+
!hash(payload.evidenceHash)) fail("UNSAFE_PROPOSAL");
|
|
298
|
+
const record = { id: document.id, subject: body.issuer, publicKey: body.publicKey, ...ctx,
|
|
299
|
+
evidenceHash: payload.evidenceHash, reviews: [], proposal: clone(payload) };
|
|
300
|
+
const measured = await this.#evidence(record);
|
|
301
|
+
this.#proposals.set(record.id, { ...record, ...measured });
|
|
302
|
+
result = { id: record.id, status: "pending", ratified: false, executionAllowed: false };
|
|
303
|
+
} else if (body.kind === "governance-vote") {
|
|
304
|
+
const record = this.#proposals.get(payload.proposalId);
|
|
305
|
+
if (!record || !sameContext(record, ctx)) fail("UNKNOWN_PROPOSAL");
|
|
306
|
+
const permission = await this.permission(body.issuer, body.publicKey, "review", ctx);
|
|
307
|
+
if (!permission.allowed) fail("TIER_DENIED");
|
|
308
|
+
this.#reviewEligibility(record, body, payload);
|
|
309
|
+
// Revalidate the author and all stored ballots before recording this one.
|
|
310
|
+
const author = await this.permission(record.subject, record.publicKey, "propose", ctx);
|
|
311
|
+
if (!author.allowed) fail("TIER_DENIED");
|
|
312
|
+
await this.#evidence(record);
|
|
313
|
+
const updated = { ...record, reviews: [...record.reviews, this.#review(body, payload)] };
|
|
314
|
+
result = await this.#proposalStatus(updated);
|
|
315
|
+
this.#proposals.set(record.id, updated);
|
|
316
|
+
} else fail("UNSUPPORTED_DOCUMENT");
|
|
317
|
+
this.#documents.set(document.id, digest(document));
|
|
318
|
+
return clone(result);
|
|
319
|
+
}
|
|
320
|
+
#reviewEligibility(record, body, payload) {
|
|
321
|
+
this.#independent(record.subject, body.issuer);
|
|
322
|
+
if (record.reviews.some(r => r.subject === body.issuer || r.publicKey === body.publicKey)) fail("DUPLICATE_REVIEW");
|
|
323
|
+
record.reviews.forEach(r => this.#independent(r.subject, body.issuer));
|
|
324
|
+
if (typeof payload.approve !== "boolean" || typeof payload.rationale !== "string" ||
|
|
325
|
+
payload.rationale.length < 3 || payload.rationale.length > 2000 ||
|
|
326
|
+
payload.evidenceHash !== record.evidenceHash) fail("INVALID_REVIEW");
|
|
327
|
+
}
|
|
328
|
+
#review(body, payload) {
|
|
329
|
+
return { subject: body.issuer, publicKey: body.publicKey, approve: payload.approve, rationale: payload.rationale };
|
|
330
|
+
}
|
|
331
|
+
async proposalStatus(id) {
|
|
332
|
+
const record = this.#proposals.get(id);
|
|
333
|
+
if (!record) fail("UNKNOWN_PROPOSAL");
|
|
334
|
+
return this.#proposalStatus(record);
|
|
335
|
+
}
|
|
336
|
+
async #proposalStatus(record) {
|
|
337
|
+
const author = await this.permission(record.subject, record.publicKey, "propose", record);
|
|
338
|
+
await this.#evidence(record);
|
|
339
|
+
const reviews = [];
|
|
340
|
+
for (const review of record.reviews) {
|
|
341
|
+
try {
|
|
342
|
+
const eligibility = await this.permission(review.subject, review.publicKey, "review", record);
|
|
343
|
+
this.#independent(record.subject, review.subject);
|
|
344
|
+
reviews.forEach(r => this.#independent(r.subject, review.subject));
|
|
345
|
+
if (eligibility.allowed) reviews.push(review);
|
|
346
|
+
} catch (error) { if (!(error instanceof GovernanceError)) throw error; }
|
|
347
|
+
}
|
|
348
|
+
const approvals = reviews.filter(r => r.approve).length;
|
|
349
|
+
const veto = reviews.some(r => !r.approve);
|
|
350
|
+
const ready = author.allowed && !veto && approvals >= this.#policy.quorum;
|
|
351
|
+
return { id: record.id, scope: record.scope, approvals, veto, status: record.scope === "global" ?
|
|
352
|
+
(ready ? "awaiting-independent-authority" : "pending") : (ready ? "local-peer-approved" : "pending"),
|
|
353
|
+
ratified: false, executionAllowed: false, rollbackHash: record.proposal.rollbackHash };
|
|
354
|
+
}
|
|
355
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Concrete transports and channel/tenant declarations
|
|
2
|
+
import type { MessageTransport } from './transport.mjs';
|
|
3
|
+
|
|
4
|
+
export interface Profile {
|
|
5
|
+
v:"agent-commons/1";id:string;namespace:string;name:string;scope:"local"|"tenant"|"global";
|
|
6
|
+
parent:string|null;revision:number;quorum:number;lexicon:Record<string,string>;fixtureHash:string;fixtures:string[];
|
|
7
|
+
benchmark:{tests:number;passed:number;originalBytes:number;wireBytes:number;reductionBps:number};
|
|
8
|
+
}
|
|
9
|
+
export interface Admission {
|
|
10
|
+
kind:"agent";publicKey:string;capabilities:string[];credentialId?:string;
|
|
11
|
+
controllerId?:string;affiliations?:string[];tenantId?:string;
|
|
12
|
+
}
|
|
13
|
+
export interface Policy {
|
|
14
|
+
mode:"local"|"global";offline?:boolean;agents:Record<string,Admission>;blocked?:string[];
|
|
15
|
+
registryUrl?:string;authorityUrl?:string;standardPins?:Record<string,string>;
|
|
16
|
+
channelsEnabled?:boolean;channels?:Record<string,{members:string[];allowForwarding?:boolean}>;tenantProfiles?:Record<string,string>;
|
|
17
|
+
}
|
|
18
|
+
export class Keychain {
|
|
19
|
+
constructor(path:string);_identity:any;static generate(options?:object):any;static localIdFromKey(key:Uint8Array):string;
|
|
20
|
+
static verifyDetached(key:string,data:Uint8Array,signature:Uint8Array):boolean;
|
|
21
|
+
load(options?:{passphrase?:string}):any;save(identity:any,options?:{passphrase?:string}):void;publicView():any;sign(data:any):Buffer;
|
|
22
|
+
}
|
|
23
|
+
export class CommonsStore {
|
|
24
|
+
constructor(path?:string);get(key:string,fallback?:any):any;set(key:string,value:any):void;
|
|
25
|
+
verify():boolean;audit():any[];close():void;db:any;
|
|
26
|
+
}
|
|
27
|
+
export class RegistryTrust {
|
|
28
|
+
constructor(options?:{policy?:Policy;client?:any;fetchImpl?:typeof fetch});
|
|
29
|
+
static isCanonicalTrust(value:unknown):boolean;
|
|
30
|
+
denyPermanently():void;
|
|
31
|
+
policy:Policy;authorize(id:string,key:string,capability?:string):Promise<any>;standards():Promise<any[]>;
|
|
32
|
+
publishedProfilePin(code:string,hash:string):Promise<any>;
|
|
33
|
+
}
|
|
34
|
+
export class AgentCommons {
|
|
35
|
+
constructor(options:{keychain:Keychain;store?:CommonsStore;policy?:Policy;carriers?:string[];transport?:MessageTransport;trust?:RegistryTrust});
|
|
36
|
+
readonly uuaid:string;readonly publicKey:string;store:CommonsStore;
|
|
37
|
+
profiles():Profile[];profile(id:string):Profile;addProfile(profile:Profile):Profile;
|
|
38
|
+
activeProfile(namespace:string):Profile;authorizedProfile(id:string):Promise<Profile>;
|
|
39
|
+
importGlobal(profile:Profile,code:string):Promise<Profile>;
|
|
40
|
+
propose(profileId:string,phrase:string):Promise<any>;vote(proposalId:string,approve:boolean,rationale?:string):Promise<any>;
|
|
41
|
+
apply(document:any):Promise<any>;prepareContribution(profileId:string,options?:{includeFixtures?:boolean}):Promise<any>;
|
|
42
|
+
send(options:{recipient:string;profileId?:string;namespace?:string;body:string;thread?:string;kind?:"message"|"profile-control";deferFlush?:boolean}):Promise<any>;
|
|
43
|
+
broadcast(options:{recipients:string[];profileId:string;body:string;thread?:string;kind?:"message"|"profile-control"}):Promise<any>;
|
|
44
|
+
receive(envelope:any):Promise<any>;flush():Promise<any[]>;poll():Promise<any[]>;status():any;
|
|
45
|
+
retryOutbox(envelopeId:string):Promise<any>;
|
|
46
|
+
}
|
|
47
|
+
export class CommonsCarrier {
|
|
48
|
+
constructor(options?:{store?:CommonsStore;trust?:RegistryTrust;keychain?:Keychain;publicUrl?:string;onEnvelope?:Function});
|
|
49
|
+
listen(port?:number,host?:string):Promise<any>;close():Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
export function createProfile(options:{namespace:string;name:string;fixtures:string[];scope?:"local"|"tenant"|"global";lexicon?:Record<string,string>;parent?:string|null;revision?:number;quorum?:number}):Profile;
|
|
52
|
+
export function verifyProfile(profile:Profile):Profile;
|
|
53
|
+
export function proposeAlias(profile:Profile,phrase:string):any;
|
|
54
|
+
export function encode(text:string,lexicon:Record<string,string>):string;
|
|
55
|
+
export function decode(text:string,lexicon:Record<string,string>):string;
|
|
56
|
+
export function benchmark(lexicon:Record<string,string>,fixtures:string[]):Profile["benchmark"];
|
|
57
|
+
export function contribution(profile:Profile,options?:{includeFixtures?:boolean}):any;
|
|
58
|
+
export function signDocument(keychain:Keychain,kind:string,payload:any):any;
|
|
59
|
+
export function verifyDocument(document:any):any;
|
|
60
|
+
export function digest(value:any):string;
|
|
61
|
+
export const BASE_PROTOCOL:"agent-commons/1";
|
|
62
|
+
export const REQUIRED_STANDARDS:string[];
|
|
63
|
+
export function initialize(options?:{home?:string;target?:"local"|"agentnet.chat"|"zilligon.com"|"zilligons.com";name?:string}):any;
|
|
64
|
+
export function loadRuntime(home?:string):{home:string;config:any;keychain:Keychain;store:CommonsStore;runtime:AgentCommons};
|
|
65
|
+
export function runAgentLoop(options:{runtime:AgentCommons;respond:Function;spontaneous?:Function;maxTurns?:number;intervalMs?:number;signal?:AbortSignal;onEvent?:Function}):Promise<{turns:number;stopped:string}>;
|
|
66
|
+
export class TrustError extends Error {code:string}
|
|
67
|
+
export class CarrierClient {constructor(options:any);deliver(envelope:any,options?:any):Promise<any>;fetchInbox(carrier:string,options?:any):Promise<any>}
|
|
68
|
+
export function localIdFromKey(key:Uint8Array):string;
|
|
69
|
+
export function seal(keychain:Keychain,body:any):any;
|
|
70
|
+
export function open(envelope:any,options?:any):{ok:boolean;reason?:string};
|
|
71
|
+
export function decrypt(keychain:Keychain,envelope:any):any;
|
|
72
|
+
export function envelopeSha(envelope:any):string;
|
|
73
|
+
export { ContinuityMemory, ContinuityError, MemoryContinuityStore, verifyContinuity, CONTINUITY_PROTOCOL } from "./continuity.mjs";
|
|
74
|
+
export interface FoundingMember {id:string;name:string;model:string;label:string;provider:string;role:string}
|
|
75
|
+
export const FOUNDING_ROSTER:readonly FoundingMember[];
|
|
76
|
+
export function initializeCohort(options:{home:string;target?:string;controllerId?:string}):any;
|
|
77
|
+
export function cohortStatus(home:string):any;
|
|
78
|
+
export class GovernanceError extends Error {code:string}
|
|
79
|
+
export function verifyGovernanceDocument(document:any):any;
|
|
80
|
+
export const CLAIM_TYPES:readonly string[];
|
|
81
|
+
export const ACTION_MANIFEST:any;
|
|
82
|
+
export function createActionBudget(options?:{scope?:"local"|"global";maxCalls?:number;maxBytes?:number;durationMs?:number;clock?:()=>number}):{consume(request:any):any;status():any};
|
|
83
|
+
export class PeerGovernance {
|
|
84
|
+
constructor(options?:{policy?:any;adapters?:Record<string,Function>;clock?:()=>number});
|
|
85
|
+
checkClaims(subject:string,key:string,context:any,required?:readonly string[]):Promise<any>;
|
|
86
|
+
credibility(subject:string,context:any):Promise<any>;
|
|
87
|
+
permission(subject:string,key:string,action:string,context:any):Promise<any>;
|
|
88
|
+
apply(document:any):Promise<any>;proposalStatus(id:string):Promise<any>;
|
|
89
|
+
}
|
|
90
|
+
export class CollaborationError extends Error {code:string}
|
|
91
|
+
export interface ModelAdapter {complete(request:{idempotencyKey:string;runId:string;phase:string;slot:any;input:any;maxTokens:number;signal?:AbortSignal}):Promise<any>}
|
|
92
|
+
export interface CollaborationOptions {model:ModelAdapter;persistence?:any;memory?:any;needs?:any;verifier?:any;artifacts?:any;roster?:any[];limits?:any;clock?:{now():number};onEvent?:Function;signal?:AbortSignal;memoryFailurePolicy?:"halt"|"best-effort";allowAdvisory?:boolean;protectedPaths?:string[];hostMaintenance?:{reason:string;authorizedPaths:string[]}}
|
|
93
|
+
export class CollaborationScheduler {
|
|
94
|
+
constructor(options:CollaborationOptions);
|
|
95
|
+
run(options:{runId:string;goal?:string;needs?:any}):Promise<any>;
|
|
96
|
+
provideNeeds(runId:string,answers:any):Promise<any>;status(runId:string):Promise<any>;cancel(reason?:string):void;
|
|
97
|
+
}
|
|
98
|
+
export function createCollaboration(options:CollaborationOptions):CollaborationScheduler;
|
|
99
|
+
export function createRoster(overrides?:any):readonly any[];
|
|
100
|
+
export function rosterFromModels(models:any):readonly any[];
|
|
101
|
+
export function createFilePersistence(directory:string,options?:{integrity?:{sign(bytes:Buffer):string|Promise<string>;verify(bytes:Buffer,signature:string):boolean|Promise<boolean>}}):any;
|
|
102
|
+
export function createMemoryPersistence():any;
|
|
103
|
+
export function createContinuity(options?:any):any;
|
|
104
|
+
export function memoryFromContinuity(journal:any,options?:any):any;
|
|
105
|
+
export function validateProposal(raw:any,options?:any):any;
|
|
106
|
+
export function validateUnifiedDiff(diff:string,path:string):any;
|
|
107
|
+
export function validatePatchPath(path:string,allowedPaths:string[],policy?:any):string;
|
|
108
|
+
export function hmacIntegrity(secret:string|Buffer):{sign(bytes:Buffer):string;verify(bytes:Buffer,signature:string):boolean};
|
|
109
|
+
export * from "./transport.mjs";
|
|
110
|
+
export * from "./channels.mjs";
|
|
111
|
+
export * from "./governance-scope.mjs";
|
package/src/index.mjs
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { AgentCommons } from "./runtime.mjs";
|
|
2
|
+
export { CommonsCarrier } from "./carrier.mjs";
|
|
3
|
+
export { CommonsStore } from "./store.mjs";
|
|
4
|
+
export { RegistryTrust, REQUIRED_STANDARDS, TrustError } from "./trust.mjs";
|
|
5
|
+
export { runAgentLoop } from "./loop.mjs";
|
|
6
|
+
export { initialize, loadRuntime } from "./config.mjs";
|
|
7
|
+
export { FOUNDING_ROSTER, initializeCohort, cohortStatus } from "./cohort.mjs";
|
|
8
|
+
export { ContinuityMemory, ContinuityError, MemoryContinuityStore, verifyContinuity, CONTINUITY_PROTOCOL } from "./continuity.mjs";
|
|
9
|
+
export { PeerGovernance, GovernanceError, verifyGovernanceDocument, createActionBudget, CLAIM_TYPES, ACTION_MANIFEST } from "./governance.mjs";
|
|
10
|
+
export { CollaborationScheduler, CollaborationError, createCollaboration, createRoster, rosterFromModels, createFilePersistence, createMemoryPersistence, createContinuity, memoryFromContinuity, validateProposal, validateUnifiedDiff, validatePatchPath, hmacIntegrity } from "./collaboration.mjs";
|
|
11
|
+
export { createProfile, verifyProfile, proposeAlias, encode, decode, benchmark, contribution, signDocument, verifyDocument, digest, BASE_PROTOCOL } from "./profiles.mjs";
|
|
12
|
+
export { Keychain, localIdFromKey, CarrierClient, seal, open, decrypt, envelopeSha } from "./pillar.mjs";
|
|
13
|
+
export { MemoryLoopbackTransport, PillarCarrierTransport } from "./transport.mjs";
|
|
14
|
+
export { classifyThread, assertChannelSendAdmission, assertChannelReceiveAdmission, assertForwardingPermission, validateTenantBinding, CANONICAL_CHANNEL_REGEX, RESERVED_CHANNEL_PREFIX } from "./channels.mjs";
|
|
15
|
+
export { classifyOperationTier, verifyPrincipalGovernance, MockPrincipalStatusVerifier } from "./governance-scope.mjs";
|