@mnemom/mnemom 0.10.0 → 0.12.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 +25 -25
- package/dist/commands/agents.js +2 -7
- package/dist/commands/api-key.d.ts +37 -0
- package/dist/commands/api-key.js +179 -0
- package/dist/commands/auth.js +1 -2
- package/dist/commands/card.js +33 -22
- package/dist/commands/governance.d.ts +85 -0
- package/dist/commands/governance.js +329 -0
- package/dist/commands/integrity.js +1 -2
- package/dist/commands/license.js +13 -4
- package/dist/commands/listen.d.ts +29 -0
- package/dist/commands/listen.js +201 -0
- package/dist/commands/logs.js +1 -3
- package/dist/commands/org.js +4 -6
- package/dist/commands/protection.js +70 -23
- package/dist/commands/recipes.d.ts +34 -0
- package/dist/commands/recipes.js +80 -0
- package/dist/commands/status.js +6 -169
- package/dist/commands/team.js +5 -10
- package/dist/commands/validate.js +7 -4
- package/dist/commands/webhooks.d.ts +61 -0
- package/dist/commands/webhooks.js +328 -0
- package/dist/index.js +489 -1
- package/dist/lib/api.d.ts +199 -2
- package/dist/lib/api.js +207 -0
- package/dist/lib/auth.js +1 -5
- package/dist/lib/format.d.ts +4 -0
- package/dist/lib/format.js +6 -0
- package/dist/lib/listen-stream.d.ts +40 -0
- package/dist/lib/listen-stream.js +101 -0
- package/dist/lib/webhooks-api.d.ts +80 -0
- package/dist/lib/webhooks-api.js +172 -0
- package/dist/smoltbot-shim.js +3 -3
- package/package.json +1 -1
- package/dist/lib/model-cache.d.ts +0 -16
- package/dist/lib/model-cache.js +0 -137
- package/dist/lib/models.d.ts +0 -41
- package/dist/lib/models.js +0 -357
- package/dist/lib/openclaw.d.ts +0 -221
- package/dist/lib/openclaw.js +0 -474
package/dist/index.js
CHANGED
|
@@ -10,10 +10,13 @@ import { protectionShowCommand, protectionPublishCommand, protectionValidateComm
|
|
|
10
10
|
import { agentsListCommand } from "./commands/agents.js";
|
|
11
11
|
import { orgListCommand, orgShowCommand } from "./commands/org.js";
|
|
12
12
|
import { teamListCommand, teamShowCommand, teamTemplateCommand, teamPreviewComposeCommand, teamAdminGrantCommand, teamAdminRevokeCommand, teamAdminListCommand, teamCoverageCommand, } from "./commands/team.js";
|
|
13
|
-
import { advisoriesListCommand, advisoriesShowCommand
|
|
13
|
+
import { advisoriesListCommand, advisoriesShowCommand } from "./commands/advisories.js";
|
|
14
14
|
import { postureListCommand, postureShowCommand, postureCreateCommand, postureUpdateCommand, postureCloneCommand, postureRevisionsCommand, postureDiffCommand, postureAssignCommand, postureUnassignCommand, posturePreviewComposeCommand, postureDeleteCommand, } from "./commands/posture.js";
|
|
15
15
|
import { loginCommand, logoutCommand, whoamiCommand } from "./commands/auth.js";
|
|
16
16
|
import { validateSafeHouseCommand } from "./commands/validate.js";
|
|
17
|
+
import { apiKeyListCommand, apiKeyCreateCommand, apiKeyRotateCommand, apiKeyRevokeCommand, } from "./commands/api-key.js";
|
|
18
|
+
import { webhooksListCommand, webhooksGetCommand, webhooksCreateCommand, webhooksUpdateCommand, webhooksDeleteCommand, webhooksRotateSecretCommand, webhooksTriggerCommand, webhooksListDeliveriesCommand, webhooksRedeliverCommand, webhooksReplayCommand, } from "./commands/webhooks.js";
|
|
19
|
+
import { listenCommand } from "./commands/listen.js";
|
|
17
20
|
program
|
|
18
21
|
.name("mnemom")
|
|
19
22
|
.description("Transparent AI agent tracing")
|
|
@@ -521,6 +524,212 @@ advisoriesCmd
|
|
|
521
524
|
}
|
|
522
525
|
});
|
|
523
526
|
// ============================================================================
|
|
527
|
+
// Governance signals (ADR-048) — operator-actionable observation surface
|
|
528
|
+
//
|
|
529
|
+
// Distinct from `mnemom advisories list` (which now narrows to runtime.* /
|
|
530
|
+
// manual.* per ADR-048 §1). Surfaces sideband.* + future protection.* /
|
|
531
|
+
// posture.* signals from governance_signals: ack/resolve/dismiss workflow,
|
|
532
|
+
// notification destinations (slack/email/pagerduty/webhook), escalation
|
|
533
|
+
// rules.
|
|
534
|
+
// ============================================================================
|
|
535
|
+
import { governanceSignalsListCommand, governanceSignalsShowCommand, governanceSignalsAckCommand, governanceSignalsResolveCommand, governanceSignalsDismissCommand, governanceDestinationsListCommand, governanceDestinationsAddCommand, governanceDestinationsRemoveCommand, governanceDestinationsTestCommand, governanceRulesListCommand, governanceRulesAddCommand, governanceRulesRemoveCommand, } from "./commands/governance.js";
|
|
536
|
+
const governanceCmd = program
|
|
537
|
+
.command("governance")
|
|
538
|
+
.description("Operator workflow for governance_signals (ADR-048)");
|
|
539
|
+
const govSignalsCmd = governanceCmd
|
|
540
|
+
.command("signals")
|
|
541
|
+
.description("List, inspect, and transition governance_signals");
|
|
542
|
+
govSignalsCmd
|
|
543
|
+
.command("list")
|
|
544
|
+
.description("List governance signals at platform/org/team/agent scope")
|
|
545
|
+
.option("--org <id>", "Org scope")
|
|
546
|
+
.option("--team <id>", "Team scope")
|
|
547
|
+
.option("--agent <id>", "Per-agent slice (signals affecting this agent)")
|
|
548
|
+
.option("--source <s>", "Filter by source (sideband.{drift,coherence,fault_line,fleet})")
|
|
549
|
+
.option("--severity <s>", "Filter by severity (info|warn|high|critical)")
|
|
550
|
+
.option("--status <s>", "Filter by status (open|acknowledged|resolved|dismissed|expired)")
|
|
551
|
+
.option("--scope <s>", "Filter by scope (platform|org|team|agent)")
|
|
552
|
+
.option("--pattern-type <s>", "Filter by pattern_type")
|
|
553
|
+
.option("--since <iso>", "Detected since (ISO timestamp)")
|
|
554
|
+
.option("--limit <n>", "Max rows (default 100, max 500)")
|
|
555
|
+
.option("--json", "Output JSON")
|
|
556
|
+
.action(async (options) => {
|
|
557
|
+
try {
|
|
558
|
+
await governanceSignalsListCommand(options);
|
|
559
|
+
}
|
|
560
|
+
catch (error) {
|
|
561
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
govSignalsCmd
|
|
566
|
+
.command("show <signal_id>")
|
|
567
|
+
.description("Show one signal in detail")
|
|
568
|
+
.option("--json", "Output JSON")
|
|
569
|
+
.action(async (signalId, options) => {
|
|
570
|
+
try {
|
|
571
|
+
await governanceSignalsShowCommand(signalId, options);
|
|
572
|
+
}
|
|
573
|
+
catch (error) {
|
|
574
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
575
|
+
process.exit(1);
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
govSignalsCmd
|
|
579
|
+
.command("ack <signal_id>")
|
|
580
|
+
.description("Acknowledge an open signal (org_admin / org_owner)")
|
|
581
|
+
.option("--action <text>", "Operator-authored action note")
|
|
582
|
+
.option("--json", "Output JSON")
|
|
583
|
+
.action(async (signalId, options) => {
|
|
584
|
+
try {
|
|
585
|
+
await governanceSignalsAckCommand(signalId, options);
|
|
586
|
+
}
|
|
587
|
+
catch (error) {
|
|
588
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
589
|
+
process.exit(1);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
govSignalsCmd
|
|
593
|
+
.command("resolve <signal_id>")
|
|
594
|
+
.description("Resolve a signal with a resolution status")
|
|
595
|
+
.requiredOption("--status <s>", "Resolution status (action_taken|wont_fix|duplicate|false_positive|self_resolved)")
|
|
596
|
+
.option("--action <text>", "Operator-authored action note")
|
|
597
|
+
.option("--json", "Output JSON")
|
|
598
|
+
.action(async (signalId, options) => {
|
|
599
|
+
try {
|
|
600
|
+
await governanceSignalsResolveCommand(signalId, options);
|
|
601
|
+
}
|
|
602
|
+
catch (error) {
|
|
603
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
604
|
+
process.exit(1);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
govSignalsCmd
|
|
608
|
+
.command("dismiss <signal_id>")
|
|
609
|
+
.description("Dismiss a signal as not actionable")
|
|
610
|
+
.option("--reason <text>", "Operator-authored dismissal reason")
|
|
611
|
+
.option("--json", "Output JSON")
|
|
612
|
+
.action(async (signalId, options) => {
|
|
613
|
+
try {
|
|
614
|
+
await governanceSignalsDismissCommand(signalId, options);
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
618
|
+
process.exit(1);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
const govDestCmd = governanceCmd
|
|
622
|
+
.command("destinations")
|
|
623
|
+
.description("Manage notification destinations (slack/email/pagerduty/webhook)");
|
|
624
|
+
govDestCmd
|
|
625
|
+
.command("list")
|
|
626
|
+
.description("List destinations for an org")
|
|
627
|
+
.requiredOption("--org <id>", "Org ID")
|
|
628
|
+
.option("--json", "Output JSON")
|
|
629
|
+
.action(async (options) => {
|
|
630
|
+
try {
|
|
631
|
+
await governanceDestinationsListCommand(options);
|
|
632
|
+
}
|
|
633
|
+
catch (error) {
|
|
634
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
govDestCmd
|
|
639
|
+
.command("add")
|
|
640
|
+
.description("Add a destination (channel + JSON config)")
|
|
641
|
+
.requiredOption("--org <id>", "Org ID")
|
|
642
|
+
.requiredOption("--channel <c>", "webhook|slack|email|pagerduty")
|
|
643
|
+
.requiredOption("--config <json>", 'Channel config (e.g., \'{"url":"...","signing_secret":"..."}\')')
|
|
644
|
+
.option("--name <n>", "Display name")
|
|
645
|
+
.option("--filter <json>", "Filter narrowing (sources/severities/etc)")
|
|
646
|
+
.option("--json", "Output JSON")
|
|
647
|
+
.action(async (options) => {
|
|
648
|
+
try {
|
|
649
|
+
await governanceDestinationsAddCommand(options);
|
|
650
|
+
}
|
|
651
|
+
catch (error) {
|
|
652
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
653
|
+
process.exit(1);
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
govDestCmd
|
|
657
|
+
.command("remove <destination_id>")
|
|
658
|
+
.description("Remove a destination")
|
|
659
|
+
.requiredOption("--org <id>", "Org ID")
|
|
660
|
+
.option("--json", "Output JSON")
|
|
661
|
+
.action(async (id, options) => {
|
|
662
|
+
try {
|
|
663
|
+
await governanceDestinationsRemoveCommand(id, options);
|
|
664
|
+
}
|
|
665
|
+
catch (error) {
|
|
666
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
667
|
+
process.exit(1);
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
govDestCmd
|
|
671
|
+
.command("test <destination_id>")
|
|
672
|
+
.description("Send a synthetic test signal through this destination")
|
|
673
|
+
.requiredOption("--org <id>", "Org ID")
|
|
674
|
+
.option("--json", "Output JSON")
|
|
675
|
+
.action(async (id, options) => {
|
|
676
|
+
try {
|
|
677
|
+
await governanceDestinationsTestCommand(id, options);
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
681
|
+
process.exit(1);
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
const govRulesCmd = governanceCmd
|
|
685
|
+
.command("rules")
|
|
686
|
+
.description("Manage escalation rules (predicate → destinations)");
|
|
687
|
+
govRulesCmd
|
|
688
|
+
.command("list")
|
|
689
|
+
.description("List escalation rules for an org")
|
|
690
|
+
.requiredOption("--org <id>", "Org ID")
|
|
691
|
+
.option("--json", "Output JSON")
|
|
692
|
+
.action(async (options) => {
|
|
693
|
+
try {
|
|
694
|
+
await governanceRulesListCommand(options);
|
|
695
|
+
}
|
|
696
|
+
catch (error) {
|
|
697
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
698
|
+
process.exit(1);
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
govRulesCmd
|
|
702
|
+
.command("add")
|
|
703
|
+
.description("Add an escalation rule (predicate JSON + destination IDs)")
|
|
704
|
+
.requiredOption("--org <id>", "Org ID")
|
|
705
|
+
.requiredOption("--name <n>", "Rule name")
|
|
706
|
+
.requiredOption("--predicate <json>", 'Predicate JSON (e.g., \'{"source":"sideband.fleet","severity_min":"high"}\')')
|
|
707
|
+
.requiredOption("--destinations <ids>", "Comma-separated destination IDs")
|
|
708
|
+
.option("--json", "Output JSON")
|
|
709
|
+
.action(async (options) => {
|
|
710
|
+
try {
|
|
711
|
+
await governanceRulesAddCommand(options);
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
715
|
+
process.exit(1);
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
govRulesCmd
|
|
719
|
+
.command("remove <rule_id>")
|
|
720
|
+
.description("Remove an escalation rule")
|
|
721
|
+
.requiredOption("--org <id>", "Org ID")
|
|
722
|
+
.option("--json", "Output JSON")
|
|
723
|
+
.action(async (id, options) => {
|
|
724
|
+
try {
|
|
725
|
+
await governanceRulesRemoveCommand(id, options);
|
|
726
|
+
}
|
|
727
|
+
catch (error) {
|
|
728
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
729
|
+
process.exit(1);
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
// ============================================================================
|
|
524
733
|
// Trust Posture (Piece 3 of T1-3.1, ADR-045)
|
|
525
734
|
//
|
|
526
735
|
// Postures are team-scoped policy input that drives the observer's sideband
|
|
@@ -764,4 +973,283 @@ validateCmd
|
|
|
764
973
|
process.exit(1);
|
|
765
974
|
}
|
|
766
975
|
});
|
|
976
|
+
// ── api-key (ADR-049 capability-based scopes) ────────────────────────────
|
|
977
|
+
const apiKeyCmd = program
|
|
978
|
+
.command("api-key")
|
|
979
|
+
.description("Manage personal API keys (capability-based scopes — ADR-049)");
|
|
980
|
+
apiKeyCmd
|
|
981
|
+
.command("list")
|
|
982
|
+
.description("List your active personal API keys with their scope sets")
|
|
983
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
984
|
+
.action(async (options) => {
|
|
985
|
+
try {
|
|
986
|
+
await apiKeyListCommand({ json: options.json });
|
|
987
|
+
}
|
|
988
|
+
catch (error) {
|
|
989
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
990
|
+
process.exit(1);
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
apiKeyCmd
|
|
994
|
+
.command("create")
|
|
995
|
+
.description("Mint a new personal API key. Default scopes: gateway, api:read, api:write. " +
|
|
996
|
+
"Admin scopes (admin:org, admin:platform) are role-gated at mint time.")
|
|
997
|
+
.requiredOption("--name <name>", "Friendly name for the key (e.g. 'ci-prod')")
|
|
998
|
+
.option("--scopes <list>", "Comma-separated capability scopes. Valid: " +
|
|
999
|
+
"gateway, api:read, api:write, admin:org, admin:platform. " +
|
|
1000
|
+
"Default: gateway,api:read,api:write")
|
|
1001
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1002
|
+
.action(async (options) => {
|
|
1003
|
+
try {
|
|
1004
|
+
await apiKeyCreateCommand({
|
|
1005
|
+
name: options.name,
|
|
1006
|
+
scopes: options.scopes,
|
|
1007
|
+
json: options.json,
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
catch (error) {
|
|
1011
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1012
|
+
process.exit(1);
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
apiKeyCmd
|
|
1016
|
+
.command("rotate <key_id>")
|
|
1017
|
+
.description("Atomic mint-new + revoke-old. Returns the new cleartext once.")
|
|
1018
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1019
|
+
.action(async (keyId, options) => {
|
|
1020
|
+
try {
|
|
1021
|
+
await apiKeyRotateCommand(keyId, { json: options.json });
|
|
1022
|
+
}
|
|
1023
|
+
catch (error) {
|
|
1024
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1025
|
+
process.exit(1);
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
apiKeyCmd
|
|
1029
|
+
.command("revoke <key_id>")
|
|
1030
|
+
.description("Soft-revoke an active key. Action is immediate and irreversible.")
|
|
1031
|
+
.action(async (keyId) => {
|
|
1032
|
+
try {
|
|
1033
|
+
await apiKeyRevokeCommand(keyId);
|
|
1034
|
+
}
|
|
1035
|
+
catch (error) {
|
|
1036
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1037
|
+
process.exit(1);
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
// ============================================================================
|
|
1041
|
+
// Webhook lifecycle commands (Track 2 W3.5)
|
|
1042
|
+
// ============================================================================
|
|
1043
|
+
const webhooksCmd = program
|
|
1044
|
+
.command("webhooks")
|
|
1045
|
+
.description("Manage webhook endpoints, deliveries, and event replay");
|
|
1046
|
+
webhooksCmd
|
|
1047
|
+
.command("list <org_id>")
|
|
1048
|
+
.description("List webhook endpoints for an org")
|
|
1049
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1050
|
+
.action(async (orgId, options) => {
|
|
1051
|
+
try {
|
|
1052
|
+
await webhooksListCommand(orgId, options);
|
|
1053
|
+
}
|
|
1054
|
+
catch (error) {
|
|
1055
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1056
|
+
process.exit(1);
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
webhooksCmd
|
|
1060
|
+
.command("get <org_id> <endpoint_id>")
|
|
1061
|
+
.description("Show details for a single webhook endpoint")
|
|
1062
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1063
|
+
.action(async (orgId, endpointId, options) => {
|
|
1064
|
+
try {
|
|
1065
|
+
await webhooksGetCommand(orgId, endpointId, options);
|
|
1066
|
+
}
|
|
1067
|
+
catch (error) {
|
|
1068
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1069
|
+
process.exit(1);
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
webhooksCmd
|
|
1073
|
+
.command("create <org_id>")
|
|
1074
|
+
.description("Create a new webhook endpoint (signing secret returned ONCE)")
|
|
1075
|
+
.requiredOption("--url <url>", "HTTPS URL to deliver events to (private/internal IPs blocked)")
|
|
1076
|
+
.option("--events <list>", "Comma-separated list of event types to subscribe to (default: none — explicit per-event opt-in)")
|
|
1077
|
+
.option("--description <text>", "Human-readable description")
|
|
1078
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1079
|
+
.action(async (orgId, options) => {
|
|
1080
|
+
try {
|
|
1081
|
+
await webhooksCreateCommand(orgId, options);
|
|
1082
|
+
}
|
|
1083
|
+
catch (error) {
|
|
1084
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1085
|
+
process.exit(1);
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
webhooksCmd
|
|
1089
|
+
.command("update <org_id> <endpoint_id>")
|
|
1090
|
+
.description("Update fields on an existing webhook endpoint")
|
|
1091
|
+
.option("--url <url>", "Replace the delivery URL")
|
|
1092
|
+
.option("--events <list>", "Replace the event-type subscription list (comma-separated)")
|
|
1093
|
+
.option("--description <text>", "Replace the description")
|
|
1094
|
+
.option("--active <bool>", "Set is_active to 'true' or 'false' (re-enabling resets failure counter)")
|
|
1095
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1096
|
+
.action(async (orgId, endpointId, options) => {
|
|
1097
|
+
try {
|
|
1098
|
+
await webhooksUpdateCommand(orgId, endpointId, options);
|
|
1099
|
+
}
|
|
1100
|
+
catch (error) {
|
|
1101
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1102
|
+
process.exit(1);
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
webhooksCmd
|
|
1106
|
+
.command("delete <org_id> <endpoint_id>")
|
|
1107
|
+
.description("Permanently delete a webhook endpoint")
|
|
1108
|
+
.action(async (orgId, endpointId) => {
|
|
1109
|
+
try {
|
|
1110
|
+
await webhooksDeleteCommand(orgId, endpointId);
|
|
1111
|
+
}
|
|
1112
|
+
catch (error) {
|
|
1113
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1114
|
+
process.exit(1);
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
webhooksCmd
|
|
1118
|
+
.command("rotate-secret <org_id> <endpoint_id>")
|
|
1119
|
+
.description("Mint a new signing secret (shown ONCE; immediately invalidates the previous secret)")
|
|
1120
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1121
|
+
.action(async (orgId, endpointId, options) => {
|
|
1122
|
+
try {
|
|
1123
|
+
await webhooksRotateSecretCommand(orgId, endpointId, options);
|
|
1124
|
+
}
|
|
1125
|
+
catch (error) {
|
|
1126
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1127
|
+
process.exit(1);
|
|
1128
|
+
}
|
|
1129
|
+
});
|
|
1130
|
+
webhooksCmd
|
|
1131
|
+
.command("trigger <org_id> <endpoint_id>")
|
|
1132
|
+
.description("Fire a synthetic test event through the full delivery pipeline (Stripe-equivalent ergonomics)")
|
|
1133
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1134
|
+
.action(async (orgId, endpointId, options) => {
|
|
1135
|
+
try {
|
|
1136
|
+
await webhooksTriggerCommand(orgId, endpointId, options);
|
|
1137
|
+
}
|
|
1138
|
+
catch (error) {
|
|
1139
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1140
|
+
process.exit(1);
|
|
1141
|
+
}
|
|
1142
|
+
});
|
|
1143
|
+
webhooksCmd
|
|
1144
|
+
.command("list-deliveries <org_id>")
|
|
1145
|
+
.description("List recent webhook deliveries (optionally scoped to one endpoint)")
|
|
1146
|
+
.option("--endpoint <endpoint_id>", "Scope to a single endpoint")
|
|
1147
|
+
.option("--limit <n>", "Maximum entries to return (default 50, max 100)")
|
|
1148
|
+
.option("--offset <n>", "Skip the first N entries (pagination)")
|
|
1149
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1150
|
+
.action(async (orgId, options) => {
|
|
1151
|
+
try {
|
|
1152
|
+
await webhooksListDeliveriesCommand(orgId, options);
|
|
1153
|
+
}
|
|
1154
|
+
catch (error) {
|
|
1155
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1156
|
+
process.exit(1);
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
webhooksCmd
|
|
1160
|
+
.command("redeliver <org_id> <delivery_id>")
|
|
1161
|
+
.description("Retry a single previous delivery (re-fires that one delivery row)")
|
|
1162
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1163
|
+
.action(async (orgId, deliveryId, options) => {
|
|
1164
|
+
try {
|
|
1165
|
+
await webhooksRedeliverCommand(orgId, deliveryId, options);
|
|
1166
|
+
}
|
|
1167
|
+
catch (error) {
|
|
1168
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1169
|
+
process.exit(1);
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
webhooksCmd
|
|
1173
|
+
.command("replay <org_id> <event_id>")
|
|
1174
|
+
.description("Re-fan-out a historical event to all currently-subscribed endpoints (or to a specified subset)")
|
|
1175
|
+
.option("--endpoint <endpoint_id>", "Only replay to the specified endpoint (repeatable)", (value, prev) => (prev ? [...prev, value] : [value]))
|
|
1176
|
+
.option("--json", "Emit raw JSON instead of rendered output")
|
|
1177
|
+
.action(async (orgId, eventId, options) => {
|
|
1178
|
+
try {
|
|
1179
|
+
await webhooksReplayCommand(orgId, eventId, options);
|
|
1180
|
+
}
|
|
1181
|
+
catch (error) {
|
|
1182
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1183
|
+
process.exit(1);
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
// ============================================================================
|
|
1187
|
+
// mnemom listen — live webhook event stream (Track 2 W3.4)
|
|
1188
|
+
// ============================================================================
|
|
1189
|
+
program
|
|
1190
|
+
.command("listen <org_id>")
|
|
1191
|
+
.description("Stream live webhook events for an org (Stripe-equivalent ergonomics)")
|
|
1192
|
+
.option("--forward-to <url>", "POST each event to this local URL (requires --secret for HMAC re-signing)")
|
|
1193
|
+
.option("--secret <hex>", "Local signing secret used to re-sign forwarded deliveries")
|
|
1194
|
+
.option("--filter <list>", "Comma-separated event types to surface (default: all)")
|
|
1195
|
+
.option("--since <event_id>", "Resume from this cursor on first connect")
|
|
1196
|
+
.option("--json", "Emit raw JSON lines instead of a formatted summary")
|
|
1197
|
+
.action(async (orgId, options) => {
|
|
1198
|
+
try {
|
|
1199
|
+
await listenCommand(orgId, options);
|
|
1200
|
+
}
|
|
1201
|
+
catch (error) {
|
|
1202
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1203
|
+
process.exit(1);
|
|
1204
|
+
}
|
|
1205
|
+
});
|
|
1206
|
+
// ============================================================================
|
|
1207
|
+
// AEGIS-6b — Customer FN/FP recipe report commands.
|
|
1208
|
+
//
|
|
1209
|
+
// `mnemom recipes report-fn <recipe-id>` / `mnemom recipes report-fp <id>`
|
|
1210
|
+
// POST to /v1/recipes/:id/report (AEGIS-6a; mnemom-api#508). The endpoint
|
|
1211
|
+
// requires customer-session auth (JWT cookie/bearer or API key) and a
|
|
1212
|
+
// non-empty summary; the CLI accepts the summary as `--summary` or via
|
|
1213
|
+
// stdin. Idempotency-Key is generated per call by postApi(); the body
|
|
1214
|
+
// fingerprint is folded server-side so a retry with corrected text returns
|
|
1215
|
+
// 422 rather than silently replaying.
|
|
1216
|
+
// ============================================================================
|
|
1217
|
+
import { recipesReportFnCommand, recipesReportFpCommand, } from "./commands/recipes.js";
|
|
1218
|
+
const recipesCmd = program
|
|
1219
|
+
.command("recipes")
|
|
1220
|
+
.description("Customer-side recipe reporting (false-negatives, false-positives)");
|
|
1221
|
+
recipesCmd
|
|
1222
|
+
.command("report-fn <recipe-id>")
|
|
1223
|
+
.description("File a false-negative report against an existing recipe (something got through that the recipe should have caught)")
|
|
1224
|
+
.option("--summary <text>", "Human-readable description of what happened (required; pipe via stdin alternatively)")
|
|
1225
|
+
.option("--evidence <text>", "Optional raw payload / log excerpt")
|
|
1226
|
+
.option("--agent <id>", "Optional. Your agent id when the report concerns a specific agent")
|
|
1227
|
+
.option("--checkpoint <id>", "Optional. Related integrity_checkpoints id (helps the reviewer correlate)")
|
|
1228
|
+
.option("--json", "Output JSON")
|
|
1229
|
+
.action(async (recipeId, options) => {
|
|
1230
|
+
try {
|
|
1231
|
+
await recipesReportFnCommand(recipeId, options);
|
|
1232
|
+
}
|
|
1233
|
+
catch (error) {
|
|
1234
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1235
|
+
process.exit(1);
|
|
1236
|
+
}
|
|
1237
|
+
});
|
|
1238
|
+
recipesCmd
|
|
1239
|
+
.command("report-fp <recipe-id>")
|
|
1240
|
+
.description("File a false-positive report against an existing recipe (the recipe fired on legitimate behaviour)")
|
|
1241
|
+
.option("--summary <text>", "Human-readable description of what happened (required; pipe via stdin alternatively)")
|
|
1242
|
+
.option("--evidence <text>", "Optional raw payload / log excerpt")
|
|
1243
|
+
.option("--agent <id>", "Optional. Your agent id when the report concerns a specific agent")
|
|
1244
|
+
.option("--checkpoint <id>", "Optional. Related integrity_checkpoints id (helps the reviewer correlate)")
|
|
1245
|
+
.option("--json", "Output JSON")
|
|
1246
|
+
.action(async (recipeId, options) => {
|
|
1247
|
+
try {
|
|
1248
|
+
await recipesReportFpCommand(recipeId, options);
|
|
1249
|
+
}
|
|
1250
|
+
catch (error) {
|
|
1251
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
1252
|
+
process.exit(1);
|
|
1253
|
+
}
|
|
1254
|
+
});
|
|
767
1255
|
program.parse();
|