@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
|