sentinelayer-cli 0.46.4 → 0.48.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/README.md +63 -3
- package/package.json +12 -7
- package/skills/omar-gate-setup/SKILL.md +103 -0
- package/skills/senti-agent-identity/SKILL.md +80 -0
- package/skills/senti-judge/SKILL.md +139 -0
- package/skills/senti-room-notifications/SKILL.md +73 -0
- package/skills/senti-room-notifications/listen-wrapper.cjs +150 -0
- package/skills/senti-room-notifications/package.json +1 -0
- package/skills/senti-room-notifications/test-classifier.js +109 -0
- package/skills/senti-room-notifications/test-receipt.js +54 -0
- package/skills/sentinelayer-cli/SKILL.md +222 -0
- package/src/agents/devtestbot/runner.js +22 -11
- package/src/agents/devtestbot/tool.js +24 -11
- package/src/agents/jules/fix-cycle.js +7 -1
- package/src/agents/jules/tools/runtime-audit.js +17 -12
- package/src/agents/shared-tools/dispatch-core.js +10 -5
- package/src/ai/aidenid.js +4 -2
- package/src/ai/domain-target-store.js +11 -5
- package/src/ai/identity-store.js +11 -5
- package/src/ai/site-store.js +8 -4
- package/src/audit/orchestrator.js +21 -14
- package/src/audit/package.js +6 -4
- package/src/audit/persona-loop.js +7 -0
- package/src/audit/replay.js +4 -2
- package/src/auth/gate.js +46 -8
- package/src/auth/service.js +34 -15
- package/src/auth/session-store.js +105 -47
- package/src/board/evidence-resolvers.js +3 -4
- package/src/cli.js +23 -3
- package/src/commands/ai/identity-lifecycle.js +30 -26
- package/src/commands/ai/provision-governance.js +32 -24
- package/src/commands/ai/shared.js +6 -4
- package/src/commands/audit.js +14 -12
- package/src/commands/auth.js +24 -4
- package/src/commands/board.js +2 -2
- package/src/commands/chat.js +8 -6
- package/src/commands/judge.js +125 -0
- package/src/commands/legacy-args.js +1 -0
- package/src/commands/mcp.js +45 -52
- package/src/commands/omargate.js +2 -1
- package/src/commands/plugin.js +11 -3
- package/src/commands/review.js +9 -4
- package/src/commands/scan.js +7 -7
- package/src/commands/session.js +607 -57
- package/src/commands/skills.js +45 -0
- package/src/commands/watch.js +9 -7
- package/src/config/output-filesystem.js +156 -0
- package/src/config/schema.js +4 -2
- package/src/config/service.js +40 -4
- package/src/cost/history.js +15 -9
- package/src/daemon/artifact-lineage.js +15 -12
- package/src/daemon/assignment-ledger.js +31 -25
- package/src/daemon/ast-drift.js +7 -3
- package/src/daemon/budget-governor.js +26 -20
- package/src/daemon/error-worker.js +28 -22
- package/src/daemon/fix-cycle.js +5 -4
- package/src/daemon/hybrid-mapper.js +19 -16
- package/src/daemon/ingest-refresh.js +4 -0
- package/src/daemon/jira-lifecycle.js +21 -17
- package/src/daemon/operator-control.js +18 -15
- package/src/daemon/reliability-lane.js +18 -15
- package/src/daemon/scope-engine.js +12 -8
- package/src/daemon/watchdog.js +15 -12
- package/src/engram/build-state.js +24 -3
- package/src/engram/capability-index.js +367 -0
- package/src/engram/compile-graph.js +1063 -0
- package/src/engram/contracts/action-receipt.js +82 -0
- package/src/engram/contracts/capability-index.js +259 -0
- package/src/engram/contracts/capability.js +377 -0
- package/src/engram/contracts/content-hash.js +8 -0
- package/src/engram/contracts/evidence.js +258 -0
- package/src/engram/contracts/graph.js +594 -0
- package/src/engram/contracts/identity.js +8 -0
- package/src/engram/contracts/index.js +149 -0
- package/src/engram/contracts/media-asset.js +85 -0
- package/src/engram/contracts/money.js +249 -0
- package/src/engram/contracts/source-snapshot.js +57 -0
- package/src/engram/contracts/task-context-pack.js +114 -0
- package/src/engram/contracts/temporal-segment.js +72 -0
- package/src/engram/contracts/versions.js +96 -0
- package/src/engram/extract-html.js +692 -0
- package/src/engram/graph-store.js +877 -0
- package/src/engram/index.js +98 -14
- package/src/engram/ingest-site.js +132 -0
- package/src/engram/live-state.js +1180 -0
- package/src/engram/namespace.js +34 -1
- package/src/engram/retrieve-site.js +753 -0
- package/src/engram/safe-reader.js +597 -0
- package/src/engram/source-intake.js +251 -0
- package/src/engram/store.js +227 -9
- package/src/ingest/engine.js +21 -28
- package/src/judge/verdict.js +305 -0
- package/src/legacy-cli.js +96 -19
- package/src/mcp/bridge-inputs.js +28 -4
- package/src/mcp/cli-command-tools.js +70 -0
- package/src/mcp/registry.js +17 -13
- package/src/mcp/session-stdio-server.js +297 -19
- package/src/memory/blackboard.js +5 -4
- package/src/net/gh-api-path.js +35 -9
- package/src/net/test-egress-guard.js +16 -4
- package/src/plugin/manifest.js +12 -8
- package/src/review/ai-review.js +110 -10
- package/src/review/investor-dd-devtestbot.js +17 -6
- package/src/review/investor-dd-orchestrator.js +21 -13
- package/src/review/local-review.js +26 -16
- package/src/review/omargate-cache.js +5 -5
- package/src/review/omargate-orchestrator.js +89 -17
- package/src/review/replay.js +9 -4
- package/src/review/report.js +22 -13
- package/src/review/typesafe-severity.js +201 -0
- package/src/session/admission-auth.js +34 -7
- package/src/session/admission.js +322 -71
- package/src/session/agent-access.js +137 -0
- package/src/session/agent-registry.js +2 -1
- package/src/session/attachment-summary.js +77 -0
- package/src/session/edit-summary.js +19 -0
- package/src/session/invitations.js +65 -1
- package/src/session/mentions.js +17 -9
- package/src/session/message-edits.js +5 -4
- package/src/session/preview.js +10 -2
- package/src/session/recap.js +3 -2
- package/src/session/room-files.js +519 -0
- package/src/session/route-classes.js +22 -8
- package/src/session/setup-guides.js +4 -0
- package/src/session/standup.js +192 -0
- package/src/session/sync.js +229 -10
- package/src/session/tickets.js +41 -0
- package/src/session/transcript.js +2 -1
- package/src/session/wake/resolve-target.js +7 -3
- package/src/skills/listener-runtime.cjs +92 -0
- package/src/skills/service.js +207 -0
- package/src/swarm/factory.js +5 -5
- package/src/swarm/pentest.js +9 -9
- package/src/swarm/report.js +4 -4
- package/src/swarm/runtime.js +15 -12
- package/src/swarm/scenario-dsl.js +7 -5
- package/src/telemetry/ledger.js +16 -7
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ENGRAM §EW02 — ActionReceipt contract.
|
|
3
|
+
*
|
|
4
|
+
* An ActionReceipt is a verifiable record of an action taken by an agent or
|
|
5
|
+
* system. It carries a content hash, timestamp, verifier identity, and a
|
|
6
|
+
* source snapshot. Receipts without these fields cannot be used to establish
|
|
7
|
+
* authoritative provenance.
|
|
8
|
+
*
|
|
9
|
+
* The contentHash and verifier fields are claims until an application checks
|
|
10
|
+
* the digest against the actual action payload and authenticates the verifier.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { sourceSnapshotSchema } from "./source-snapshot.js";
|
|
15
|
+
import { sha256ContentHashSchema } from "./content-hash.js";
|
|
16
|
+
|
|
17
|
+
export const ACTION_RECEIPT_STATUSES = Object.freeze([
|
|
18
|
+
"executed",
|
|
19
|
+
"failed",
|
|
20
|
+
"pending",
|
|
21
|
+
"rolled_back",
|
|
22
|
+
]);
|
|
23
|
+
|
|
24
|
+
export const actionReceiptStatusSchema = z.enum([
|
|
25
|
+
"executed",
|
|
26
|
+
"failed",
|
|
27
|
+
"pending",
|
|
28
|
+
"rolled_back",
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A verifiable receipt for an action performed in the system.
|
|
33
|
+
*
|
|
34
|
+
* Every receipt carries a content hash over the action payload, the
|
|
35
|
+
* verifier identity, and a source snapshot. The contentHash format is a
|
|
36
|
+
* scheme-prefixed digest (e.g. "sha256:<hex>") for integrity checking;
|
|
37
|
+
* full signature verification is deferred to a future contract version.
|
|
38
|
+
*/
|
|
39
|
+
export const actionReceiptSchema = z.object({
|
|
40
|
+
receiptId: z.string().min(1),
|
|
41
|
+
action: z.string().min(1),
|
|
42
|
+
status: actionReceiptStatusSchema,
|
|
43
|
+
performedAt: z.string().datetime(),
|
|
44
|
+
verifier: z.string().min(1),
|
|
45
|
+
contentHash: sha256ContentHashSchema,
|
|
46
|
+
sourceSnapshot: sourceSnapshotSchema,
|
|
47
|
+
tenantScope: z.string().min(1),
|
|
48
|
+
evidenceRefs: z.array(z.string().min(1)).optional(),
|
|
49
|
+
metadata: z.record(z.string(), z.json()).optional(),
|
|
50
|
+
}).strict().refine(
|
|
51
|
+
(data) => {
|
|
52
|
+
// Tenant scope must be consistent with sourceSnapshot.
|
|
53
|
+
if (data.tenantScope !== data.sourceSnapshot.tenantScope) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
message: "tenantScope must match sourceSnapshot.tenantScope; cross-tenant requires explicit authorization",
|
|
60
|
+
path: ["tenantScope"],
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Valid fixture: a complete, valid action receipt.
|
|
66
|
+
*/
|
|
67
|
+
export const VALID_ACTION_RECEIPT = Object.freeze({
|
|
68
|
+
receiptId: "rec-exec-abc123",
|
|
69
|
+
action: "graph.validate",
|
|
70
|
+
status: "executed",
|
|
71
|
+
performedAt: "2026-10-23T12:00:01Z",
|
|
72
|
+
verifier: "aidenid-verifier-01",
|
|
73
|
+
contentHash: "sha256:nji40eArkmG6ZZyc3Od23mge2TYew/f4vFc/wTBwCOE=",
|
|
74
|
+
sourceSnapshot: {
|
|
75
|
+
sourceId: "src-session-abc123",
|
|
76
|
+
sourceType: "session",
|
|
77
|
+
version: "1.2.0",
|
|
78
|
+
capturedAt: "2026-10-23T12:00:00Z",
|
|
79
|
+
tenantScope: "tenant/acme",
|
|
80
|
+
},
|
|
81
|
+
tenantScope: "tenant/acme",
|
|
82
|
+
});
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ENGRAM §EW08 — Capability Index and Skill Descriptor contracts.
|
|
3
|
+
*
|
|
4
|
+
* Defines:
|
|
5
|
+
* - skillSchema: a single capability skill descriptor (MCP-tool-compatible)
|
|
6
|
+
* - capabilityIndexSchema: a deterministic, versioned, digest-signed index
|
|
7
|
+
* of all advertised skills for a publisher origin.
|
|
8
|
+
*
|
|
9
|
+
* Every skill in the index maps onto an MCP tool descriptor unchanged so a
|
|
10
|
+
* later MCP adapter (EW20) reuses it. The index carries a sha256 digest over
|
|
11
|
+
* the canonical JSON of its body (sans the digest field) so a consumer can
|
|
12
|
+
* verify integrity without trusting the transport.
|
|
13
|
+
*
|
|
14
|
+
* All schemas are strict: extra fields are rejected.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { capabilityVersionSchema } from "./capability.js";
|
|
19
|
+
import { sha256ContentHashSchema } from "./content-hash.js";
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Skill descriptor
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
/** Valid scope values for a skill. */
|
|
26
|
+
const SKILL_SCOPE = z.enum(["read", "write"]);
|
|
27
|
+
|
|
28
|
+
/** Valid side-effect classifications. */
|
|
29
|
+
const SKILL_SIDE_EFFECTS = z.enum(["none", "simulated", "real"]);
|
|
30
|
+
|
|
31
|
+
/** Valid visibility levels. */
|
|
32
|
+
const SKILL_VISIBILITY = z.enum(["public", "private"]);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A bounded text field: plain text, no control characters, size-capped.
|
|
36
|
+
* MCP tools have titles and descriptions; this is the ENGRAM equivalent
|
|
37
|
+
* for a skill descriptor that can be projected onto a tool unchanged.
|
|
38
|
+
*/
|
|
39
|
+
const boundedTextField = (maxLen, label) =>
|
|
40
|
+
z.string()
|
|
41
|
+
.min(1, `${label} must not be empty`)
|
|
42
|
+
.max(maxLen, `${label} exceeds ${maxLen} characters`)
|
|
43
|
+
.refine((s) => !/[\u0000-\u001f\u007f-\u009f]/.test(s), {
|
|
44
|
+
message: `${label} must not contain control characters`,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* A single capability skill descriptor.
|
|
49
|
+
*
|
|
50
|
+
* Fields project directly onto MCP tool annotations:
|
|
51
|
+
* - name + title + description → tool identity
|
|
52
|
+
* - inputSchema / outputSchema → JSON Schema objects (size-bounded)
|
|
53
|
+
* - readOnlyHint / destructiveHint / idempotentHint → scope + sideEffects
|
|
54
|
+
* - requiresConfirmation → a client UX gate
|
|
55
|
+
* - fallback → what to show when the capability is unavailable
|
|
56
|
+
*
|
|
57
|
+
* Private skills are NEVER included in a public index.
|
|
58
|
+
*/
|
|
59
|
+
export const skillSchema = z.object({
|
|
60
|
+
capability: z.string().regex(/^[a-z][a-z0-9_-]{0,47}$/),
|
|
61
|
+
version: capabilityVersionSchema,
|
|
62
|
+
title: boundedTextField(128, "title"),
|
|
63
|
+
purpose: boundedTextField(1024, "purpose"),
|
|
64
|
+
inputSchema: z.record(z.unknown()).refine(
|
|
65
|
+
(s) => JSON.stringify(s).length <= 8192,
|
|
66
|
+
{ message: "inputSchema JSON must not exceed 8192 bytes" },
|
|
67
|
+
),
|
|
68
|
+
outputSchema: z.record(z.unknown()).refine(
|
|
69
|
+
(s) => JSON.stringify(s).length <= 8192,
|
|
70
|
+
{ message: "outputSchema JSON must not exceed 8192 bytes" },
|
|
71
|
+
),
|
|
72
|
+
scope: SKILL_SCOPE,
|
|
73
|
+
sideEffects: SKILL_SIDE_EFFECTS,
|
|
74
|
+
requiresConfirmation: z.boolean(),
|
|
75
|
+
fallback: z.string().max(2048).optional(),
|
|
76
|
+
visibility: SKILL_VISIBILITY,
|
|
77
|
+
}).strict().superRefine((skill, ctx) => {
|
|
78
|
+
if (!versionNameMatches(skill.capability, skill.version)) {
|
|
79
|
+
ctx.addIssue({
|
|
80
|
+
code: "custom",
|
|
81
|
+
path: ["version"],
|
|
82
|
+
message: "version name must match capability",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
// Capability index
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A publisher origin: an https origin with no path, query, or fragment.
|
|
93
|
+
*/
|
|
94
|
+
const publisherOriginSchema = z.string().refine((s) => {
|
|
95
|
+
try {
|
|
96
|
+
const u = new URL(s);
|
|
97
|
+
return (
|
|
98
|
+
u.protocol === "https:" &&
|
|
99
|
+
u.hostname.length > 0 &&
|
|
100
|
+
u.pathname === "/" &&
|
|
101
|
+
u.search === "" &&
|
|
102
|
+
u.hash === "" &&
|
|
103
|
+
u.username === "" &&
|
|
104
|
+
u.password === ""
|
|
105
|
+
);
|
|
106
|
+
} catch {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}, { message: "publisherOrigin must be an https origin with no path" });
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* An ISO-8601 datetime string in UTC (must end with Z).
|
|
113
|
+
*/
|
|
114
|
+
const utcDatetimeSchema = z.string().refine(
|
|
115
|
+
(s) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/.test(s),
|
|
116
|
+
{ message: "datetime must be ISO-8601 in UTC (ending with Z)" },
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A deterministic capability index for a publisher origin.
|
|
121
|
+
*
|
|
122
|
+
* Layout:
|
|
123
|
+
* - publisherOrigin: who published this index (https origin)
|
|
124
|
+
* - indexVersion: monotonic version of the index format
|
|
125
|
+
* - issuedAt / expiresAt: validity window
|
|
126
|
+
* - revoked: list of capability versions that are no longer valid
|
|
127
|
+
* - skills: only public, implemented skills sorted by capability name
|
|
128
|
+
* - digest: sha256 of the canonical JSON of the index WITHOUT this field
|
|
129
|
+
*
|
|
130
|
+
* The digest lets a consumer verify the index is intact: strip digest,
|
|
131
|
+
* canonicalize, sha256, compare. If they don't match, the index is tampered
|
|
132
|
+
* or corrupted.
|
|
133
|
+
*/
|
|
134
|
+
export const capabilityIndexSchema = z.object({
|
|
135
|
+
publisherOrigin: publisherOriginSchema,
|
|
136
|
+
indexVersion: z.string().regex(/^\d+\.\d+\.\d+$/),
|
|
137
|
+
issuedAt: utcDatetimeSchema,
|
|
138
|
+
expiresAt: utcDatetimeSchema,
|
|
139
|
+
revoked: z.array(capabilityVersionSchema).default([]),
|
|
140
|
+
skills: z.array(skillSchema),
|
|
141
|
+
digest: sha256ContentHashSchema,
|
|
142
|
+
}).strict().superRefine((index, ctx) => {
|
|
143
|
+
// Every revoked entry must correspond to a version of a capability that
|
|
144
|
+
// exists (or existed) — validate the format at minimum.
|
|
145
|
+
for (let i = 0; i < index.revoked.length; i++) {
|
|
146
|
+
const r = index.revoked[i];
|
|
147
|
+
if (!capabilityVersionSchema.safeParse(r).success) {
|
|
148
|
+
ctx.addIssue({
|
|
149
|
+
code: "custom",
|
|
150
|
+
path: ["revoked", i],
|
|
151
|
+
message: `revoked entry "${r}" is not a valid capability version`,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Skills must be sorted by capability name (deterministic output).
|
|
157
|
+
for (let i = 1; i < index.skills.length; i++) {
|
|
158
|
+
if (index.skills[i].capability < index.skills[i - 1].capability) {
|
|
159
|
+
ctx.addIssue({
|
|
160
|
+
code: "custom",
|
|
161
|
+
path: ["skills", i],
|
|
162
|
+
message: "skills must be sorted by capability name",
|
|
163
|
+
});
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// No private skills in a published index.
|
|
169
|
+
for (let i = 0; i < index.skills.length; i++) {
|
|
170
|
+
if (index.skills[i].visibility === "private") {
|
|
171
|
+
ctx.addIssue({
|
|
172
|
+
code: "custom",
|
|
173
|
+
path: ["skills", i, "visibility"],
|
|
174
|
+
message: "private skills must not appear in a published index",
|
|
175
|
+
});
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// expiresAt must be after issuedAt.
|
|
181
|
+
if (new Date(index.expiresAt) <= new Date(index.issuedAt)) {
|
|
182
|
+
ctx.addIssue({
|
|
183
|
+
code: "custom",
|
|
184
|
+
path: ["expiresAt"],
|
|
185
|
+
message: "expiresAt must be after issuedAt",
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Helpers
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Check that a capability version's name prefix matches the expected
|
|
196
|
+
* capability name.
|
|
197
|
+
*/
|
|
198
|
+
function versionNameMatches(capability, version) {
|
|
199
|
+
const parts = parseCapVersion(version);
|
|
200
|
+
return parts !== null && parts[0] === capability;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Parse a capability version string into [name, major, minor, patch].
|
|
205
|
+
* Returns null if the string does not match.
|
|
206
|
+
*/
|
|
207
|
+
function parseCapVersion(v) {
|
|
208
|
+
if (typeof v !== "string") return null;
|
|
209
|
+
const m = v.match(
|
|
210
|
+
/^([a-z][a-z0-9_-]{0,47})@(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/,
|
|
211
|
+
);
|
|
212
|
+
if (!m) return null;
|
|
213
|
+
return [m[1], Number(m[2]), Number(m[3]), Number(m[4])];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
// Errors
|
|
218
|
+
// ---------------------------------------------------------------------------
|
|
219
|
+
|
|
220
|
+
/** Base error for capability index operations. */
|
|
221
|
+
export class CapabilityIndexError extends Error {
|
|
222
|
+
constructor(message, evidence) {
|
|
223
|
+
super(message);
|
|
224
|
+
this.name = "CapabilityIndexError";
|
|
225
|
+
this.evidence = evidence ?? null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** The index digest does not match the computed digest over the body. */
|
|
230
|
+
export function digestMismatch(expected, actual, evidence) {
|
|
231
|
+
return new CapabilityIndexError(
|
|
232
|
+
`digest mismatch: expected ${expected}, computed ${actual}`,
|
|
233
|
+
evidence,
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** The index has expired. */
|
|
238
|
+
export function indexExpired(expiresAt, now, evidence) {
|
|
239
|
+
return new CapabilityIndexError(
|
|
240
|
+
`index expired at ${expiresAt} (now: ${now})`,
|
|
241
|
+
evidence,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** The index publisher origin does not match the expected origin. */
|
|
246
|
+
export function originMismatch(expected, actual, evidence) {
|
|
247
|
+
return new CapabilityIndexError(
|
|
248
|
+
`origin mismatch: expected ${expected}, got ${actual}`,
|
|
249
|
+
evidence,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** A requested capability has been revoked. */
|
|
254
|
+
export function capabilityRevoked(capability, version, evidence) {
|
|
255
|
+
return new CapabilityIndexError(
|
|
256
|
+
`capability ${capability} version ${version} has been revoked`,
|
|
257
|
+
evidence,
|
|
258
|
+
);
|
|
259
|
+
}
|