@brightbeamai/chap-coordinator 0.2.9 → 0.2.10
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 +6 -1
- package/dist/{api-DE78DA0o.d.cts → api-CcT_8H5j.d.cts} +13 -0
- package/dist/{api-CPEk0V6i.d.ts → api-Cvkhcalw.d.ts} +13 -0
- package/dist/api.d.cts +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/index.cjs +91 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +91 -3
- package/dist/index.js.map +1 -1
- package/dist/jsonrpc.cjs +2 -0
- package/dist/jsonrpc.cjs.map +1 -1
- package/dist/jsonrpc.d.cts +2 -0
- package/dist/jsonrpc.d.ts +2 -0
- package/dist/jsonrpc.js +2 -0
- package/dist/jsonrpc.js.map +1 -1
- package/dist/methods.cjs.map +1 -1
- package/dist/methods.d.cts +22 -2
- package/dist/methods.d.ts +22 -2
- package/dist/storage/sqlite.cjs +5 -2
- package/dist/storage/sqlite.cjs.map +1 -1
- package/dist/storage/sqlite.js +4 -9
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/storage/store.cjs.map +1 -1
- package/dist/storage/store.d.cts +26 -1
- package/dist/storage/store.d.ts +26 -1
- package/dist/storage/store.js.map +1 -1
- package/package.json +79 -27
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CoordinatorOptions, a as Coordinator } from './api-
|
|
2
|
-
export { b as CoordinatorApi, c as CoordinatorError, d as CredentialVerifier, E as EscalationPolicyFn, H as Handler, I as IdFactory, P as PRIVILEGED_METHODS, R as ReviewDepthPolicyFn, e as RoutingPolicyFn, S as ScittReceiptVerifier, f as ScittSubmitter, T as TokenVerifier, g as call, m as makeApi } from './api-
|
|
1
|
+
import { C as CoordinatorOptions, a as Coordinator } from './api-CcT_8H5j.cjs';
|
|
2
|
+
export { b as CoordinatorApi, c as CoordinatorError, d as CredentialVerifier, E as EscalationPolicyFn, H as Handler, I as IdFactory, P as PRIVILEGED_METHODS, R as ReviewDepthPolicyFn, e as RoutingPolicyFn, S as ScittReceiptVerifier, f as ScittSubmitter, T as TokenVerifier, g as call, m as makeApi } from './api-CcT_8H5j.cjs';
|
|
3
3
|
export { MethodName, MethodParams, MethodResult, MethodTable } from './methods.cjs';
|
|
4
4
|
export { MemoryStore, Store, WorkspaceRecord } from './storage/store.cjs';
|
|
5
5
|
export { ArtefactId, ArtefactRoutingHints, AuditEntry, AuditListener, Deliberation, DeliberationVote, Envelope, Handoff, HandoffTaskItem, JsonPatchOp, Jwk, KeyRecord, Member, Mode, OverrideArtefact, ParticipantType, ParticipantUri, PauseScope, ReviewDecision, RouteDecisionArtefact, SnapshotArtefact, Task, TaskId, TaskRoutingHints, TaskState, WhisperPrompt, Workspace, WorkspaceId, WorkspaceState, modeLE } from './types.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CoordinatorOptions, a as Coordinator } from './api-
|
|
2
|
-
export { b as CoordinatorApi, c as CoordinatorError, d as CredentialVerifier, E as EscalationPolicyFn, H as Handler, I as IdFactory, P as PRIVILEGED_METHODS, R as ReviewDepthPolicyFn, e as RoutingPolicyFn, S as ScittReceiptVerifier, f as ScittSubmitter, T as TokenVerifier, g as call, m as makeApi } from './api-
|
|
1
|
+
import { C as CoordinatorOptions, a as Coordinator } from './api-Cvkhcalw.js';
|
|
2
|
+
export { b as CoordinatorApi, c as CoordinatorError, d as CredentialVerifier, E as EscalationPolicyFn, H as Handler, I as IdFactory, P as PRIVILEGED_METHODS, R as ReviewDepthPolicyFn, e as RoutingPolicyFn, S as ScittReceiptVerifier, f as ScittSubmitter, T as TokenVerifier, g as call, m as makeApi } from './api-Cvkhcalw.js';
|
|
3
3
|
export { MethodName, MethodParams, MethodResult, MethodTable } from './methods.js';
|
|
4
4
|
export { MemoryStore, Store, WorkspaceRecord } from './storage/store.js';
|
|
5
5
|
export { ArtefactId, ArtefactRoutingHints, AuditEntry, AuditListener, Deliberation, DeliberationVote, Envelope, Handoff, HandoffTaskItem, JsonPatchOp, Jwk, KeyRecord, Member, Mode, OverrideArtefact, ParticipantType, ParticipantUri, PauseScope, ReviewDecision, RouteDecisionArtefact, SnapshotArtefact, Task, TaskId, TaskRoutingHints, TaskState, WhisperPrompt, Workspace, WorkspaceId, WorkspaceState, modeLE } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -211,6 +211,7 @@ var E = {
|
|
|
211
211
|
NOT_AUTHORISED: -32011,
|
|
212
212
|
PATCH_FAILED: -32012,
|
|
213
213
|
REVIEW_LAPSED: -32013,
|
|
214
|
+
REVIEW_ALREADY_OPEN: -32014,
|
|
214
215
|
// whisper/1.0 profile (profiles/whisper.md S6)
|
|
215
216
|
WHISPER_ALREADY_ANSWERED: -32020,
|
|
216
217
|
WHISPER_LAPSED: -32021,
|
|
@@ -237,6 +238,7 @@ var E = {
|
|
|
237
238
|
SIG_KEY_NOT_FOUND: -32071,
|
|
238
239
|
SIG_KEY_REVOKED: -32072,
|
|
239
240
|
SIG_ROTATION_KEY_MISMATCH: -32073,
|
|
241
|
+
SIG_ARTEFACT_DIGEST_MISMATCH: -32074,
|
|
240
242
|
// audit-scitt/1.0 profile (profiles/audit-scitt.md S8)
|
|
241
243
|
SCITT_UNREACHABLE: -32080,
|
|
242
244
|
SCITT_STATEMENT_REJECTED: -32081,
|
|
@@ -704,6 +706,12 @@ function registerAuditScitt(coord) {
|
|
|
704
706
|
if (!(ws.chain_enabled || coord.options.enableChain)) {
|
|
705
707
|
return { error: rpcError(E.PARAMS, "Chain not enabled for this workspace") };
|
|
706
708
|
}
|
|
709
|
+
if (p.from_seq !== void 0 || p.to_seq !== void 0) {
|
|
710
|
+
return { error: rpcError(
|
|
711
|
+
E.PARAMS,
|
|
712
|
+
"Range verification is not implemented; omit from_seq and to_seq to verify the whole log."
|
|
713
|
+
) };
|
|
714
|
+
}
|
|
707
715
|
let start = ws.audit.findIndex((e) => e.prev_hash != null);
|
|
708
716
|
if (start < 0) start = ws.audit.length;
|
|
709
717
|
const errors = [];
|
|
@@ -715,16 +723,35 @@ function registerAuditScitt(coord) {
|
|
|
715
723
|
}
|
|
716
724
|
prev = sha256Hex(Buffer.concat([canonicalize(e.envelope), Buffer.from(expectedPrev, "utf-8")]));
|
|
717
725
|
}
|
|
718
|
-
const storedHead = ws.chain_head
|
|
726
|
+
const storedHead = ws.chain_head === void 0 || ws.chain_head === null ? ZERO_HASH : ws.chain_head;
|
|
719
727
|
if (prev !== storedHead) {
|
|
720
728
|
errors.push("chain_head mismatch: replay does not match stored head");
|
|
721
729
|
}
|
|
722
730
|
if (errors.length) {
|
|
723
731
|
return { error: rpcError(E.PARAMS, errors.join("; ")) };
|
|
724
732
|
}
|
|
733
|
+
const entriesTotal = ws.audit.length;
|
|
734
|
+
const entriesChecked = entriesTotal - start;
|
|
735
|
+
const entriesUnchecked = start;
|
|
736
|
+
if (entriesUnchecked > 0) {
|
|
737
|
+
return { result: {
|
|
738
|
+
status: "not_evaluated",
|
|
739
|
+
ok: false,
|
|
740
|
+
reason: "unchained_prefix",
|
|
741
|
+
entries_total: entriesTotal,
|
|
742
|
+
entries_checked: entriesChecked,
|
|
743
|
+
entries_unchecked: entriesUnchecked,
|
|
744
|
+
checked_from_seq: entriesChecked > 0 ? ws.audit[start].seq : null,
|
|
745
|
+
chain_head: storedHead
|
|
746
|
+
} };
|
|
747
|
+
}
|
|
725
748
|
return { result: {
|
|
749
|
+
status: "verified",
|
|
726
750
|
ok: true,
|
|
727
|
-
|
|
751
|
+
entries_total: entriesTotal,
|
|
752
|
+
entries_checked: entriesChecked,
|
|
753
|
+
entries_unchecked: 0,
|
|
754
|
+
checked_from_seq: entriesChecked > 0 ? ws.audit[start].seq : null,
|
|
728
755
|
chain_head: storedHead
|
|
729
756
|
} };
|
|
730
757
|
});
|
|
@@ -2415,12 +2442,38 @@ var Coordinator = class {
|
|
|
2415
2442
|
const reviewers = Array.isArray(to) ? to : typeof to === "string" ? [to] : [];
|
|
2416
2443
|
if (!reviewers.length) return { error: rpcError(E.PARAMS, "review.request needs 'to'") };
|
|
2417
2444
|
const now = this.now();
|
|
2445
|
+
const rule = p.rule || "any_one_approves";
|
|
2446
|
+
if (task.state === "review_requested" && task.review) {
|
|
2447
|
+
if (contentHash(task.pending_artefact) !== contentHash(p.artefact)) {
|
|
2448
|
+
return { error: rpcError(
|
|
2449
|
+
E.REVIEW_ALREADY_OPEN,
|
|
2450
|
+
"A review is already open on this task with different content. Decide, abstain, escalate or cancel it before requesting review of a new artefact."
|
|
2451
|
+
) };
|
|
2452
|
+
}
|
|
2453
|
+
if (rule !== task.review.rule) {
|
|
2454
|
+
return { error: rpcError(
|
|
2455
|
+
E.REVIEW_ALREADY_OPEN,
|
|
2456
|
+
`Cannot change the decision rule of an open review (currently ${task.review.rule})`
|
|
2457
|
+
) };
|
|
2458
|
+
}
|
|
2459
|
+
for (const r of reviewers) {
|
|
2460
|
+
if (!task.review.requested_to.includes(r)) task.review.requested_to.push(r);
|
|
2461
|
+
}
|
|
2462
|
+
if (p.deadline !== void 0) task.review.deadline = p.deadline;
|
|
2463
|
+
task.updated_at = now;
|
|
2464
|
+
return { result: {
|
|
2465
|
+
state: "review_requested",
|
|
2466
|
+
review_id: task.id,
|
|
2467
|
+
amended: true,
|
|
2468
|
+
requested_to: [...task.review.requested_to]
|
|
2469
|
+
} };
|
|
2470
|
+
}
|
|
2418
2471
|
task.state = "review_requested";
|
|
2419
2472
|
task.updated_at = now;
|
|
2420
2473
|
task.review = {
|
|
2421
2474
|
requested_at: now,
|
|
2422
2475
|
requested_to: reviewers,
|
|
2423
|
-
rule
|
|
2476
|
+
rule,
|
|
2424
2477
|
deadline: p.deadline,
|
|
2425
2478
|
decisions: []
|
|
2426
2479
|
};
|
|
@@ -2428,6 +2481,37 @@ var Coordinator = class {
|
|
|
2428
2481
|
task.pending_artefact = p.artefact;
|
|
2429
2482
|
return { result: { state: "review_requested", review_id: task.id } };
|
|
2430
2483
|
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Verify an optional `approved_artefact_digest` against the artefact under
|
|
2486
|
+
* review (review/1.0 S3.2).
|
|
2487
|
+
*
|
|
2488
|
+
* The digest sits in params, so it is inside whatever the envelope signature
|
|
2489
|
+
* covers: the decision then attests the content the reviewer saw rather than
|
|
2490
|
+
* a task reference, and a relying party can check it without trusting the
|
|
2491
|
+
* Coordinator that produced it. Absent, behaviour is exactly as before.
|
|
2492
|
+
*
|
|
2493
|
+
* On mismatch nothing is recorded and no state changes, so a client that
|
|
2494
|
+
* computes the wrong digest refuses only its own decision.
|
|
2495
|
+
*/
|
|
2496
|
+
checkArtefactDigest(p, task) {
|
|
2497
|
+
const declared = p.approved_artefact_digest;
|
|
2498
|
+
if (declared === void 0 || declared === null) return null;
|
|
2499
|
+
if (typeof declared !== "string") {
|
|
2500
|
+
return { error: rpcError(E.PARAMS, "approved_artefact_digest must be a string") };
|
|
2501
|
+
}
|
|
2502
|
+
if (task.pending_artefact === void 0) {
|
|
2503
|
+
return { error: rpcError(E.PARAMS, "No artefact under review to bind a digest to") };
|
|
2504
|
+
}
|
|
2505
|
+
const actual = contentHash(task.pending_artefact);
|
|
2506
|
+
if (declared !== actual) {
|
|
2507
|
+
return { error: rpcError(
|
|
2508
|
+
E.SIG_ARTEFACT_DIGEST_MISMATCH,
|
|
2509
|
+
"approved_artefact_digest does not match the artefact under review",
|
|
2510
|
+
{ declared, actual }
|
|
2511
|
+
) };
|
|
2512
|
+
}
|
|
2513
|
+
return null;
|
|
2514
|
+
}
|
|
2431
2515
|
opDecide(p, kind) {
|
|
2432
2516
|
const miss = missing(p, ["workspace", "from", "task_id"]);
|
|
2433
2517
|
if (miss) return { error: rpcError(E.PARAMS, `Missing field: ${miss}`) };
|
|
@@ -2444,6 +2528,8 @@ var Coordinator = class {
|
|
|
2444
2528
|
}
|
|
2445
2529
|
const notReviewer = this.requireReviewer(task, p.from);
|
|
2446
2530
|
if (notReviewer) return notReviewer;
|
|
2531
|
+
const digestError = this.checkArtefactDigest(p, task);
|
|
2532
|
+
if (digestError) return digestError;
|
|
2447
2533
|
const now = this.now();
|
|
2448
2534
|
task.review.decisions.push({
|
|
2449
2535
|
reviewer: p.from,
|
|
@@ -2478,6 +2564,8 @@ var Coordinator = class {
|
|
|
2478
2564
|
}
|
|
2479
2565
|
const notReviewer = this.requireReviewer(task, p.from);
|
|
2480
2566
|
if (notReviewer) return notReviewer;
|
|
2567
|
+
const digestError = this.checkArtefactDigest(p, task);
|
|
2568
|
+
if (digestError) return digestError;
|
|
2481
2569
|
const base = task.pending_artefact;
|
|
2482
2570
|
if (base === void 0) return { error: rpcError(E.PARAMS, "No base artefact for override") };
|
|
2483
2571
|
let applied;
|