@decidio/sdk 0.9.0 → 0.11.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/CHANGELOG.md +83 -0
- package/README.md +2 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +860 -38
- package/openapi.yaml +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,89 @@ the gate, signing, receipts and the verifier - is conformance-locked between the
|
|
|
5
5
|
first-run surfaces (the fork, `--demo`, the code sign-in) are TypeScript-first and named as such in the parity
|
|
6
6
|
allowlist. Each entry names what changed, what a reader must do on upgrade, and what proved it.
|
|
7
7
|
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
## 0.11.0 — connect once, on in every project; no surprises; the connector connects a computer
|
|
11
|
+
|
|
12
|
+
0.10.0 was never published (its tag was held for this release), so 0.11.0 is the first release with `connect`. It carries
|
|
13
|
+
cycle connect-once's slice 1, 2a and 2b (founder 2026-10-29: one tag, after they merge).
|
|
14
|
+
|
|
15
|
+
- **One connect per computer.** A connection now covers every repository on the computer, and `connect` switches the hook
|
|
16
|
+
on in your own `~/.claude/settings.json`, which every project reads. A repository connected the 0.10.0 way keeps its own
|
|
17
|
+
connection (read first). A cloud session and `--team` still use the repository's `.claude/settings.json`.
|
|
18
|
+
- **The hook connects the computer itself.** A destructive command on a computer with no credential is refused with a link
|
|
19
|
+
and a short code (to Claude, and in a line to the person); once the workspace owner allows it, the next try finishes
|
|
20
|
+
connecting and asks for the approval in the same run. It never writes Claude Code's settings - in auto mode the assistant
|
|
21
|
+
may not, and a person put the hook there. Two hooks at once share one link. It connects only the Decidio your shell
|
|
22
|
+
names (or the default), never one a repository's `.env` names, and only over HTTPS; a project whose `.env` names an agent
|
|
23
|
+
with no token is refused by name rather than given the computer's connection. The run that connects tells the person which
|
|
24
|
+
workspace and who allowed it, even when the command then runs at once.
|
|
25
|
+
- **The computer-wide hook is the pinned `npx -y @decidio/sdk@0.11.0` command**, so it works in every project; a project
|
|
26
|
+
install still writes `$CLAUDE_PROJECT_DIR` unescaped, so Claude Code expands it. The settings file is written whole, and
|
|
27
|
+
through a symlink.
|
|
28
|
+
- **No surprises** (founder 2026-10-29: "the user is fully aware and not surprised"):
|
|
29
|
+
- `hook session`, a SessionStart hook: every session opens with one line - approvals are on here, what waits and for whom,
|
|
30
|
+
or that this computer isn't connected yet. Local only, never blocks;
|
|
31
|
+
- `connect` says what waits for approval and that everything else runs as before;
|
|
32
|
+
- a held command names who approves and where they see it;
|
|
33
|
+
- the plugin skill says what connecting does before doing it, and has the person run `! npx @decidio/sdk connect` when
|
|
34
|
+
auto mode refuses it.
|
|
35
|
+
- **The plugin** (0.5.0) carries the SessionStart hook, and a marketplace file ready to publish - not published (founder:
|
|
36
|
+
nothing public until the listing is ready).
|
|
37
|
+
- **The connector connects a computer** (slice 2a):
|
|
38
|
+
- `connect --ticket <ticket>` finishes the link the Decidio connector allowed (`connect_device` returns the ticket): the
|
|
39
|
+
poll carries this computer's own secret and the ticket, and only the credential is written;
|
|
40
|
+
- the hook names the connector's way first when a computer isn't connected (call `connect_device` with the code, run what
|
|
41
|
+
it returns), then the link and code; a link the connector allowed is kept while it waits for its ticket.
|
|
42
|
+
- **Pause and resume** (slice 2b): `hook prompt`, a UserPromptSubmit hook that `hook install`, `connect` and the plugin add
|
|
43
|
+
behind a shell pre-filter, acts on the person's own typed "decidio pause" / "decidio start" (exact words, `source: user`
|
|
44
|
+
only) and keeps the words from the model. While paused a gated command runs with a line and no decision - asked of Decidio only
|
|
45
|
+
in a session paused on this computer; the settings guard (now run over the whole line, inside `sh -c` too, for the pause and
|
|
46
|
+
the shared file's notice alike) and the self-decide refusal stay on; an agent running `hook prompt` itself is refused. The
|
|
47
|
+
session line says how to pause, or that the organisation keeps the guard on.
|
|
48
|
+
- **A shared file tells, then lets through** (slice 2a): `hook pretool --unconnected=tell`, which `connect` writes into a
|
|
49
|
+
shared file, refuses a computer with no credential once per session and command, then lets the same call pass with a line
|
|
50
|
+
to the person - never an `allow`, so Claude Code's own permission check still decides. No flag, a value it doesn't know,
|
|
51
|
+
or no session id holds, as before. `connect --team --hold-everyone` writes the holding hook instead.
|
|
52
|
+
|
|
53
|
+
On upgrade: nothing to do; 0.10.0 repository connections keep working. Proved by: cli-smoke.ts (378 -> 400; slice 1: one connect for
|
|
54
|
+
two repositories, the 0.10.0 file read first, the hook's own link - wait - collect-then-ask without touching settings, two
|
|
55
|
+
hooks sharing a link, a refused link, the approver in holds, the session line, SessionStart installed; slice 2a: the
|
|
56
|
+
connector's way, the ticket's usage, secret and ticket on the poll, tell once then a line, hold by default, --hold-everyone).
|
|
57
|
+
|
|
58
|
+
## 0.10.0 — connect a coding assistant in one tap (not published; folded into 0.11.0)
|
|
59
|
+
|
|
60
|
+
- **`npx @decidio/sdk connect`** (cycle connect). A coding assistant sets Decidio up for you: it runs `connect`, which prints a
|
|
61
|
+
link and a short code (on a real terminal also a QR, and it opens the browser); the workspace owner opens the link signed in,
|
|
62
|
+
checks the code, picks who approves and taps Allow; `connect --wait` then returns by itself (exit 0 connected, 1 still
|
|
63
|
+
waiting - run it again, 3 refused or expired; within 90 s, under an assistant's 2-minute command limit). The machine gets an
|
|
64
|
+
ask-only credential - never a session - kept OUTSIDE the repository (the config dir, owner-only, keyed by the repository root
|
|
65
|
+
and the Decidio), and the hooks switch on in `.claude/settings.local.json` (`--team`: the shared `.claude/settings.json`).
|
|
66
|
+
No `.env`, nothing to paste, the word "agent" nowhere in the setup.
|
|
67
|
+
- **In a cloud session the hooks go in `.claude/settings.json`.** A cloud session reads the repository's files, not your
|
|
68
|
+
computer's, and only the committed shared file reaches the next cloud machine, so that is where they go. connect leaves it uncommitted and says to ask
|
|
69
|
+
the person before committing it (committed, every cloud session of the repository and every teammate's clone ask too). The
|
|
70
|
+
credential is that cloud machine's: a fresh one refuses destructive commands until it connects again.
|
|
71
|
+
- **The machine proves its key.** The start is signed with the machine's own key (the request-bound proof every signed
|
|
72
|
+
request carries, over the assistant, project, machine and cloud-or-local), so nobody can file a connect in another
|
|
73
|
+
machine's name; the server refuses a start without it. The connect checks the wire first (https, or a local address),
|
|
74
|
+
since the poll's answer carries the credential.
|
|
75
|
+
- **Credentials, in order:** the shell, then the folder's `.env`, then this repository's connection - all or nothing, so a
|
|
76
|
+
project with an `init` `.env` keeps exactly that identity. `disconnect` deletes this machine's token (gated commands are then
|
|
77
|
+
refused until you connect again; the machine's key stays, so reconnecting reuses its agent).
|
|
78
|
+
- **The hook's words** for an unconnected project now name `connect` and `connect --wait` (the plugin's skill says the same);
|
|
79
|
+
`hook install` with no credentials points at `connect` first.
|
|
80
|
+
- **The links the command line prints follow the API's own web app** (launch plan L1c). Staging's API maps to
|
|
81
|
+
`staging.decidioai.com`, production's (`mcp.decidioai.com`) to `app.decidioai.com`, and any other origin to itself.
|
|
82
|
+
`DECIDIO_APP_URL` wins only as a plain `http(s)` address, and the host line names it.
|
|
83
|
+
- **Release condition:** publish only after `staging.decidioai.com` serves staging's web app (docs/Deployment_Runbook.md
|
|
84
|
+
A1). Tell testers to run `github init` again to refresh their AGENTS.md section.
|
|
85
|
+
|
|
86
|
+
On upgrade: nothing to change - `init` projects keep their `.env`. The plugin pins 0.10.0. `connect` needs a Decidio that
|
|
87
|
+
serves `/connect/*` (the lab, from cycle connect's deploy). Proved by: cli-smoke.ts (356 → 378 checks: connect, its signed
|
|
88
|
+
start, wait, reconnect, disconnect, refused, expired, a cloud session, --team, beside the plugin, .env precedence, the hook
|
|
89
|
+
through a connection).
|
|
90
|
+
|
|
8
91
|
## 0.9.0 — the coding-agent hook catches what agents type, protects itself, and tells the approver what was asked
|
|
9
92
|
|
|
10
93
|
- **Wider matching, from real agent runs.** `sql-destructive` counts a statement sent through an interpreter or runner
|
package/README.md
CHANGED
|
@@ -75,8 +75,8 @@ npx @decidio/sdk init --unique my-agent # --unique appends a random suffix: co
|
|
|
75
75
|
Every network command talks to the hosted sandbox by default (`verify` is offline) and announces its target host on
|
|
76
76
|
stderr each run — set `DECIDIO_API_URL` (env or `.env`) to point at another Decidio instead.
|
|
77
77
|
|
|
78
|
-
`init` signs you into your workspace (
|
|
79
|
-
|
|
78
|
+
`init` signs you into your workspace (the 8-character code the CLI emails you — type it where you asked —
|
|
79
|
+
or, for an account made before sign-up became passwordless, its email + password), generates the agent's Ed25519 keypair **locally** (only the public `did:key`
|
|
80
80
|
is sent), registers the agent, mints its **floor-limited API token** (limited to the agent runtime — request authorization, poll status, report signed confirmation; it cannot administer the workspace or approve anything — and your workspace session never touches the agent's disk), and writes `.env`.
|
|
81
81
|
Every later command that talks to Decidio reads `.env` from this directory automatically (`verify` is
|
|
82
82
|
offline and never does). Re-running init for an
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
export declare function appUrlFor(api: string, override?: string | undefined): string;
|
|
2
3
|
export type ApprovalAnswer = "approve" | "reject" | "again";
|
|
3
4
|
export declare function approvalAnswer(answer: unknown): ApprovalAnswer;
|
|
4
5
|
/** The issuer store's key for a Decidio address: its origin (scheme + lowercased host + non-default port), computed by a
|
|
@@ -17,6 +18,8 @@ export declare function defaultAgentId(dir?: string): string;
|
|
|
17
18
|
* distinct decision ids can never share a file (first-run review of 0.4.1: dots were STRIPPED, `a.b` and `ab`
|
|
18
19
|
* collided). `~` is outside the allowed set, so the escape is unambiguous. Exported for the smokes. */
|
|
19
20
|
export declare function receiptFileName(id: string): string;
|
|
21
|
+
/** Exactly what the person types to pause or resume the guard - nothing else is read. PURE. */
|
|
22
|
+
export declare function guardWords(prompt: unknown): "pause" | "start" | null;
|
|
20
23
|
/** Scoped packs (GitHub App design §2): a pack's scope in words - the organisation's, a unit's (its type, and its name when
|
|
21
24
|
* the server sent one: names that fail its person check are withheld there), or the reader's own. Null for an older server. */
|
|
22
25
|
export declare function packScopeLabel(scope: any): string | null;
|