actradeck 0.5.2 → 0.7.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 CHANGED
@@ -1,8 +1,10 @@
1
1
  # actradeck
2
2
 
3
- > Bootstrap CLI for **ActraDeck** a local-first control plane for coding agents (Claude
4
- > Code, Codex, …): observe them, redact secrets before they're stored, gate high-risk actions
5
- > behind approvals, and keep a tamper-evident audit trail.
3
+ > Put risky Claude Code and Codex actions back in front of a human.
4
+
5
+ ActraDeck is a local approval and audit cockpit for coding agents. This package gives you
6
+ a zero-side-effect product preview, diagnoses the machine, and verifies the full product
7
+ before handing off to its quickstart.
6
8
 
7
9
  This package is a **thin, dependency-free bootstrapper**. It does not contain the product —
8
10
  the full four-tier stack ships as a **signed GitHub Release** and a **signed GHCR image**.
@@ -14,19 +16,28 @@ The CLI helps you _get to_ a running cockpit and verify what you download.
14
16
  - **Fail-closed verification.** `install` checks the release's sha256 checksum _and_ its
15
17
  SLSA build provenance before extracting a single file.
16
18
 
19
+ ## See the safety story first
20
+
21
+ ```sh
22
+ npx actradeck@latest demo
23
+ ```
24
+
25
+ `demo` prints a five-second **synthetic preview** of detect → hold → deny → redact →
26
+ record. It executes no command, writes no file, starts no subprocess, and makes no network
27
+ request. The output then points to the cockpit's 30-second demo, which exercises the real
28
+ ingestion, redaction, projection, and audit pipeline.
29
+
17
30
  ## Usage
18
31
 
19
32
  ```sh
33
+ npx actradeck@latest demo # safe synthetic preview; no side effects or network
20
34
  npx actradeck@latest doctor # diagnose: platform / Node / pnpm / git / Docker (offline-safe)
21
35
  npx actradeck@latest install # verify + fetch the latest signed release, then quickstart
22
36
  npx actradeck@latest up # print the Docker cockpit command (prints only; runs nothing)
23
37
  npx actradeck@latest version # your CLI version + whether a newer stable release exists
38
+ npx actradeck@latest conformance < events.jsonl # check an adapter's stream vs the contract
24
39
  ```
25
40
 
26
- > **Not published yet.** The first npm publish is planned for **v0.5** (see the project's ADR
27
- > 0013). Until then the commands above describe the intended flow; the canonical, already-signed
28
- > way to get ActraDeck is the GitHub Release / GHCR image or `scripts/install.sh` from the repo.
29
-
30
41
  ### `install`
31
42
 
32
43
  Resolves the latest stable GitHub Release (or `--version vX.Y.Z`), downloads the source
@@ -35,7 +46,7 @@ provenance (`gh attestation verify`), then extracts and hands off to the repo's
35
46
  `scripts/quickstart`.
36
47
 
37
48
  ```sh
38
- npx actradeck@latest install --version v0.4.0 # a specific tag
49
+ npx actradeck@latest install --version v0.7.0 # a specific tag
39
50
  npx actradeck@latest install --dry-run # resolve + verify only; change nothing
40
51
  npx actradeck@latest install --skip-provenance # explicit opt-out (checksum still enforced)
41
52
  ```
@@ -45,12 +56,39 @@ and provenance is verified unless you pass `--skip-provenance` (which requires y
45
56
  the reduced guarantee). `--skip-provenance` exists only for machines that cannot install the
46
57
  GitHub CLI.
47
58
 
59
+ ### `conformance`
60
+
61
+ Validate that a third-party ingestion adapter's event stream satisfies the ActraDeck ingestion
62
+ contract — **without cloning the monorepo**. Capture your adapter's emitted NormalizedEvents as
63
+ **JSONL** (one JSON object per line, in emission order) and pipe them in:
64
+
65
+ ```sh
66
+ npx actradeck@latest conformance < events.jsonl # read JSONL from stdin
67
+ npx actradeck@latest conformance events.jsonl # or from a file
68
+ npx actradeck@latest conformance events.jsonl --json # machine-readable JSON report
69
+ ```
70
+
71
+ It checks the stream-level and cross-field invariants a single-event schema parse cannot see:
72
+ every event parses as a NormalizedEvent; `payload.kind === event_type`; per-session `timestamp` is
73
+ non-decreasing; and per-session `seq`, when present, is a dense 0-based counter (so the backend can
74
+ detect silent mid-stream drops — a session that emits no `seq` is a **warning**, not an error). A
75
+ repeated `event_id` or `seq` is a **warning**, not an error — an at-least-once retry is legitimate
76
+ and the backend dedupes it (§3.3 / §4.4). Redaction is **not** checked: the backend ingress
77
+ redaction floor is the sole redaction point, so an adapter cannot and need not prove it.
78
+
79
+ **Exit codes:** `0` = conformant (warnings allowed) · `1` = one or more errors · `2` = usage /
80
+ input error. The checker core is ActraDeck's canonical `checkConformance`, bundled into this CLI at
81
+ build time — the published package still has **zero runtime dependencies**. It is the same check as
82
+ the in-repo `scripts/check-conformance.mjs` (see `docs/ingestion-contract.md` §8); for piped output
83
+ it is byte-identical (an interactive TTY differs only in ANSI color). The input is read fully into
84
+ memory, which suits adapter sample streams rather than an unbounded live feed.
85
+
48
86
  ## Environment
49
87
 
50
- | Variable | Default | Meaning |
51
- | ----------------------- | -------------------- | --------------------------------------------------- |
52
- | `ACTRADECK_REPO` | `actradeck/actradeck`| `owner/name` (or git URL) to resolve releases from |
53
- | `ACTRADECK_INSTALL_DIR` | `~/actradeck` | where `install` extracts the verified source |
88
+ | Variable | Default | Meaning |
89
+ | ----------------------- | --------------------- | -------------------------------------------------- |
90
+ | `ACTRADECK_REPO` | `actradeck/actradeck` | `owner/name` (or git URL) to resolve releases from |
91
+ | `ACTRADECK_INSTALL_DIR` | `~/actradeck` | where `install` extracts the verified source |
54
92
 
55
93
  ## License
56
94
 
@@ -0,0 +1,41 @@
1
+ ActraDeck CLI — third-party notices for code bundled into dist/lib/conformance-core.js.
2
+ The `conformance` command inlines the checker's dependency closure at build time; the
3
+ licenses of those bundled packages follow.
4
+
5
+ ==============================================================================
6
+ uuid@11.1.1 (MIT)
7
+ ==============================================================================
8
+ The MIT License (MIT)
9
+
10
+ Copyright (c) 2010-2020 Robert Kieffer and other contributors
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17
+
18
+ ==============================================================================
19
+ zod@4.4.3 (MIT)
20
+ ==============================================================================
21
+ MIT License
22
+
23
+ Copyright (c) 2025 Colin McDonnell
24
+
25
+ Permission is hereby granted, free of charge, to any person obtaining a copy
26
+ of this software and associated documentation files (the "Software"), to deal
27
+ in the Software without restriction, including without limitation the rights
28
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29
+ copies of the Software, and to permit persons to whom the Software is
30
+ furnished to do so, subject to the following conditions:
31
+
32
+ The above copyright notice and this permission notice shall be included in all
33
+ copies or substantial portions of the Software.
34
+
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41
+ SOFTWARE.
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import type { Deps } from "./lib/types.js";
2
2
  import { type InstallOpts } from "./commands/install.js";
3
+ import { type ConformanceOpts } from "./commands/conformance.js";
3
4
  export declare function parseInstallOpts(args: string[]): InstallOpts;
5
+ export declare function parseConformanceOpts(args: string[]): ConformanceOpts;
4
6
  export declare function run(deps: Deps, argv: string[]): Promise<number>;
package/dist/cli.js CHANGED
@@ -2,12 +2,15 @@ import { cmdDoctor } from "./commands/doctor.js";
2
2
  import { cmdUp } from "./commands/up.js";
3
3
  import { cmdVersion } from "./commands/version.js";
4
4
  import { cmdInstall } from "./commands/install.js";
5
- const USAGE = `actradeck bootstrap CLI for ActraDeck (local-first control plane for coding agents)
5
+ import { cmdConformance } from "./commands/conformance.js";
6
+ import { cmdDemo } from "./commands/demo.js";
7
+ const USAGE = `actradeck — put risky coding-agent actions back in front of a human
6
8
 
7
9
  Usage:
8
10
  actradeck <command> [options]
9
11
 
10
12
  Commands:
13
+ demo Show a 5-second safety preview. No install, files, subprocesses, or network.
11
14
  doctor Diagnose this machine (platform / Node / pnpm / git / Docker). Offline-safe.
12
15
  install Fetch + VERIFY a signed release (checksum + provenance), then hand off to quickstart.
13
16
  --version vX.Y.Z install a specific release tag (default: latest stable)
@@ -15,6 +18,10 @@ Commands:
15
18
  --skip-provenance checksum-only (explicit opt-out; not recommended)
16
19
  up Print the Docker cockpit bring-up command (prints only — does not run it).
17
20
  version Print this CLI's version and whether a newer stable release is available.
21
+ conformance Validate an adapter's JSONL event stream against the ingestion contract.
22
+ [file] read JSONL from a file (default: stdin)
23
+ --json emit a machine-readable JSON report instead of the summary
24
+ Exit: 0 = conformant · 1 = one or more errors · 2 = usage/setup error.
18
25
 
19
26
  Global:
20
27
  -h, --help show this help
@@ -53,6 +60,11 @@ export function parseInstallOpts(args) {
53
60
  }
54
61
  return { version, dryRun, skipProvenance };
55
62
  }
63
+ export function parseConformanceOpts(args) {
64
+ const json = args.includes("--json");
65
+ const file = args.find((a) => !a.startsWith("--"));
66
+ return file !== undefined ? { file, json } : { json };
67
+ }
56
68
  export async function run(deps, argv) {
57
69
  const cmd = argv[0];
58
70
  const rest = argv.slice(1);
@@ -70,12 +82,16 @@ export async function run(deps, argv) {
70
82
  return 0;
71
83
  case "doctor":
72
84
  return await cmdDoctor(deps);
85
+ case "demo":
86
+ return await cmdDemo(deps);
73
87
  case "up":
74
88
  return await cmdUp(deps);
75
89
  case "version":
76
90
  return await cmdVersion(deps);
77
91
  case "install":
78
92
  return await cmdInstall(deps, parseInstallOpts(rest));
93
+ case "conformance":
94
+ return await cmdConformance(deps, parseConformanceOpts(rest));
79
95
  default:
80
96
  deps.io.err(`Unknown command: ${cmd}`);
81
97
  deps.io.out(USAGE);
@@ -0,0 +1,8 @@
1
+ import type { Deps } from "../lib/types.js";
2
+ import type { ConformanceReport } from "../lib/conformance-types.js";
3
+ export interface ConformanceOpts {
4
+ file?: string;
5
+ json: boolean;
6
+ }
7
+ export declare function cmdConformance(deps: Deps, opts: ConformanceOpts): Promise<number>;
8
+ export declare function renderHuman(report: ConformanceReport, malformed: Map<number, string>): string[];
@@ -0,0 +1,57 @@
1
+ export async function cmdConformance(deps, opts) {
2
+ let raw;
3
+ try {
4
+ raw = await deps.readInput(opts.file);
5
+ }
6
+ catch (err) {
7
+ const code = err.code ?? (err instanceof Error ? err.message : String(err));
8
+ deps.io.err(`conformance: could not read input (${code})`);
9
+ return 2;
10
+ }
11
+ const events = [];
12
+ const malformed = new Map();
13
+ for (const line of raw.split("\n")) {
14
+ const trimmed = line.trim();
15
+ if (trimmed.length === 0)
16
+ continue;
17
+ const index = events.length;
18
+ try {
19
+ events.push(JSON.parse(trimmed));
20
+ }
21
+ catch (err) {
22
+ malformed.set(index, err instanceof Error ? err.message : String(err));
23
+ events.push({});
24
+ }
25
+ }
26
+ const report = await deps.checkConformance(events);
27
+ if (opts.json) {
28
+ deps.io.out(JSON.stringify(report, null, 2));
29
+ return report.ok ? 0 : 1;
30
+ }
31
+ for (const line of renderHuman(report, malformed))
32
+ deps.io.out(line);
33
+ return report.ok ? 0 : 1;
34
+ }
35
+ export function renderHuman(report, malformed) {
36
+ const lines = [];
37
+ lines.push(`conformance: ${report.total} events · ${report.schemaValid} schema-valid · ${report.sessions} session(s)`);
38
+ for (const f of report.findings)
39
+ lines.push(findingLine(f, malformed));
40
+ if (report.ok) {
41
+ const suffix = report.warnings > 0 ? ` (${report.warnings} warning(s))` : "";
42
+ lines.push(`PASS — the stream conforms to the ingestion contract${suffix}`);
43
+ }
44
+ else {
45
+ lines.push(`FAIL — ${report.errors} error(s), ${report.warnings} warning(s)`);
46
+ }
47
+ return lines;
48
+ }
49
+ function findingLine(f, malformed) {
50
+ const where = f.index >= 0 ? `event ${f.index}` : "stream";
51
+ const sess = f.sessionId ? ` [session ${f.sessionId}]` : "";
52
+ const message = f.rule === "schema" && malformed.has(f.index)
53
+ ? `not valid JSON: ${malformed.get(f.index)}`
54
+ : f.message;
55
+ const tag = f.severity === "error" ? "ERROR" : "WARN";
56
+ return ` ${tag} ${where}${sess} (${f.rule}): ${message}`;
57
+ }
@@ -0,0 +1,2 @@
1
+ import type { Deps } from "../lib/types.js";
2
+ export declare function cmdDemo(deps: Deps): Promise<number>;
@@ -0,0 +1,28 @@
1
+ export async function cmdDemo(deps) {
2
+ deps.io.out(`ActraDeck safety preview
3
+
4
+ SAFE SIMULATION — no command is executed, no file is changed, and no network call is made.
5
+
6
+ Claude Code requests:
7
+ rm -rf ./important-directory
8
+
9
+ [HIGH RISK] recursive filesystem delete detected
10
+ [HELD] waiting for a human decision
11
+ [DENIED] no approval received; safe-side timeout
12
+
13
+ Agent output contains:
14
+ GITHUB_TOKEN=[REDACTED:github-token]
15
+
16
+ [RECORDED] decision + redacted event added to the replayable audit trail
17
+
18
+ That is ActraDeck's first job: put risky coding-agent actions back in front of you.
19
+
20
+ Try the real ingestion -> approval -> redaction -> audit pipeline:
21
+ docker run --rm -p 127.0.0.1:55400:55400 -v actradeck_pgdata:/data \\
22
+ ghcr.io/actradeck/actradeck:latest
23
+ then open http://localhost:55400 and click "Run the 30-second safety demo".
24
+
25
+ Detection is best-effort, not a sandbox. Read the documented limits:
26
+ https://github.com/actradeck/actradeck/blob/main/SECURITY.md`);
27
+ return 0;
28
+ }