@stackbone/cli 0.3.1 → 0.3.3

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 CHANGED
@@ -7,6 +7,111 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.3] - 2026-08-11
11
+
12
+ ### Added
13
+
14
+ - **The folder `stackbone package` writes now brings object storage, not just a
15
+ database and a queue.** The generated compose already shipped a pgvector
16
+ Postgres because of managed RAG, but managed RAG stores the ingested original
17
+ in a bucket before it chunks and embeds it. So an operator who ran
18
+ `docker compose up -d` got the vector database and nowhere to put files:
19
+ ingestion died on the first upload, `client.storage` answered
20
+ `s3_credentials_missing`, and the file browser had nothing to talk to, while
21
+ `/health` said `ok` throughout because it only probes Postgres and Redis. The
22
+ compose now brings a MinIO plus a one-shot container that creates the bucket,
23
+ and the agent waits for the bucket to exist rather than for MinIO to be
24
+ healthy. Unlike the two datastores, this one publishes a port and generates
25
+ its own password: a presigned download link carries the endpoint it was
26
+ signed with, so a link signed against an address only the compose network
27
+ resolves is useless to a browser.
28
+ - **The folder also gains a `.env.example`,** rendered from the same template as
29
+ the real `.env` so the committable copy cannot drift into a stale list of
30
+ variables.
31
+ - **`STACKBONE_S3_FORCE_PATH_STYLE` picks how the box addresses its bucket.** It
32
+ was hardcoded to path-style, which made every subdomain-only backend (AWS S3,
33
+ Railway Buckets) unusable. Additive, and still defaulting to path-style, which
34
+ is what the bundled MinIO speaks.
35
+
36
+ ### Fixed
37
+
38
+ - **`stackbone build` now ships the config schema itself, not just a flag saying
39
+ one exists.** `stackbone dev` extracted the creator's `config.schema.ts` and
40
+ served the Studio config form off it; `build` stamped `config: { schema: true }`
41
+ on the manifest and emitted no schema. A packaged box found nothing on disk and
42
+ degraded the form to a raw JSON field with writes unvalidated, so a config that
43
+ worked in dev silently did not in the box. The compiler now writes the artifact
44
+ using the same extractor `dev` runs. A declared schema that will not convert
45
+ warns and ships without the file rather than failing the build.
46
+ - **`stackbone link` teaches the box which installation it answers for.** The box
47
+ learns its organization and installation id at registration, and the browser
48
+ wizard already did this; `link` registered a deployment and taught nothing, so
49
+ every box linked from the terminal refused all Studio and CLI traffic with a
50
+ 401 blaming a tenant mismatch that did not exist. `link` now holds the same
51
+ prove, teach, then write order as the wizard, and fails closed: a box that
52
+ cannot be taught is not registered at all.
53
+ - **A box locks its secrets with the key the agent opens them with.** A secret
54
+ written from Studio or the CLI landed encrypted under the documented dev seed,
55
+ while `client.secrets.get()` inside the agent decrypts with the per-agent
56
+ `STACKBONE_SECRET_KEY`. The row was there and the read still failed, so a
57
+ workflow reported the secret as missing. Only deployed boxes were affected;
58
+ `stackbone dev` falls back to the same seed on both sides. **Secrets stored
59
+ under the old key cannot be recovered and have to be set again once the new
60
+ image is running.**
61
+ - **A box defaults to the Stackbone control plane and says so at boot.**
62
+ `STACKBONE_CONTROL_PLANE_URL` had no default and nothing in the product set
63
+ it, so a box armed no browser-identity verifier and answered 401 on every
64
+ Studio screen. It now falls back to `https://api.stackbone.ai`, and the boot
65
+ line prints which control plane it armed against and whether the operator
66
+ chose it. A box belonging to a self-hosted control plane still has to name it.
67
+
68
+ ### Changed
69
+
70
+ - **An identity token is minted per organization, and names the box it is for.**
71
+ The old mint read the caller's earliest-joined membership, so an operator in
72
+ two organizations got a token no box in the second one accepts, carrying their
73
+ role from the first. The token now also carries the installation it was minted
74
+ for, and a box admits a request only when that claim matches the installation
75
+ it answers for: a token lifted off one box is worthless against the next.
76
+ - **The box says which check refused the request.** One code answered three
77
+ different refusals, and the copy named the signature, so an operator whose real
78
+ problem was the token's organization went and checked a secret, a clock and a
79
+ container that were all fine. Now `invalid_signature`, `invalid_token` and
80
+ `invalid_token_tenant` are distinct. Nothing about who is admitted changed.
81
+
82
+ ## [0.3.2] - 2026-08-10
83
+
84
+ ### Added
85
+
86
+ - **`stackbone link` refuses a box the control plane could not work with, before
87
+ it writes anything.** The command registered whatever answered the URL, so a
88
+ container too old to be registered from the browser could still be linked from
89
+ the terminal without a word — and the failure surfaced later, on the first
90
+ screen that needed something the box does not speak, with a deployment row on
91
+ file to explain it. `link` now reads the box's public handshake
92
+ (`GET <url>/api/contract`, no credential) right after it resolves the agent and
93
+ before it verifies `--secret`, and refuses with the same sentence the browser
94
+ wizard prints. A box that never answers, one that answers with something that
95
+ is not a handshake, and one that is simply too old each fail in their own
96
+ words. Nothing is written on refusal: no deployment, no local project file.
97
+
98
+ ### Changed
99
+
100
+ - **The agent protocol the box reports goes from 14 to 15, `stackbone dev`
101
+ included.** The box now permits the `stackbone-signature` request header on a
102
+ cross-origin preflight, which is what lets a browser sign a challenge against
103
+ it. Nothing on the wire changes shape and no capability moves — the number is
104
+ the change, and it is what a caller reads to know the box has it. The origin
105
+ allowlist is untouched: one more permitted header is not one more permitted
106
+ origin.
107
+ - **`stackbone package` says how a managed Redis URL is written.** The generated
108
+ `.env` and README carried `redis://host:6379`, which no managed provider
109
+ accepts: they all hand out a password, some require TLS, and a password
110
+ containing `/`, `+`, `=` or `@` has to be percent-encoded or the URL does not
111
+ parse. All three are now spelled out where the operator reads them, next to the
112
+ note that the agent PINGs Redis before starting and stops with the reason if it
113
+ cannot.
114
+
10
115
  ## [0.3.1] - 2026-08-06
11
116
 
12
117
  ### Added