@vibecompass/vibecompass 0.14.0 → 0.15.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 CHANGED
@@ -1,5 +1,70 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.0 - 2026-09-25
4
+
5
+ - Add a layered local credential store for hosted sync tokens (D-355). Every
6
+ hosted command now resolves the token in a fixed order: the binding's env
7
+ var when set (per-shell override for CI, automation, and agents), then the
8
+ per-user credential store keyed by hosted URL + project id. The store lives
9
+ outside every project root (`VIBECOMPASS_CONFIG_DIR`, else
10
+ `$XDG_CONFIG_HOME/vibecompass`, else `~/.config/vibecompass`;
11
+ `%APPDATA%\vibecompass` on Windows); its `credentials.json` index is
12
+ written `0600` inside a `0700` directory and a world-readable file is
13
+ refused. Secrets go to the OS keychain when one is available (macOS
14
+ Keychain via `security`, Linux `secret-tool`) and otherwise into the file;
15
+ the index records which backend holds each entry. `project.yaml` is
16
+ unchanged (`credential_source: env` + `credential_env_var` stay required),
17
+ so older CLIs keep working against the env var.
18
+ - `connect-hosted` captures the token after writing the binding: a hidden
19
+ prompt on a TTY, `--token-stdin` for scripts and agents, `--no-store` to
20
+ keep the env-only path, and `--credential-store <auto|keychain|file>`.
21
+ When the env var is already set it says so and points at
22
+ `sync-credential set --from-env` instead of storing silently.
23
+ - Add `vibecompass login [--sync-target <name>] [--api-url <url>]
24
+ [--project-id <id>] [--label <text>] [--no-browser] [--poll-timeout <s>]`:
25
+ a browser device-code sign-in. The CLI prints and opens the dashboard
26
+ approval link with a short code, polls until the project owner approves,
27
+ stores the minted token, and writes the sync binding when the root is not
28
+ bound yet (promoting `local-only` to `local-primary` like `connect-hosted`).
29
+ An unknown `--sync-target` is created only with an explicit `--api-url`;
30
+ a mismatched `--api-url` on a bound root fails closed.
31
+ - Add `vibecompass sync-credential <set|remove|list>`: store a dashboard
32
+ token (hidden prompt, `--token-stdin`, or `--from-env`), forget one, or
33
+ list stored entries (metadata only, never values; `--json`). `--api-url`
34
+ + `--project-id` address a hosted project without a bound root.
35
+ - `status` prints `Hosted sync:` and `Sync credential:` lines (source only:
36
+ env var, OS keychain, credential store file, or missing) and recommends
37
+ `vibecompass login` when nothing holds a token. Missing-credential errors
38
+ from push, pull, mode transitions, and hosted docs-review now name
39
+ `login` first, then `sync-credential set`, then the env var override.
40
+ - Init and connect-hosted no longer tell users to export the token in
41
+ every terminal or persist it in a shell profile.
42
+ - Credential store hardening (review passes 1–3): every store mutation
43
+ takes a cross-process lock file next to the index that appears atomically
44
+ (owner record hard-linked into place) and names its owner (id, pid, host).
45
+ The lock is never taken from a live process on this host, however long it
46
+ waits on a keychain prompt; writers wait up to 10s, then fail naming the
47
+ owner. A lock whose owner process no longer exists is recovered through a
48
+ second reclaim lock so exactly one reclaimer removes it after re-reading
49
+ the owner; locks from another host, unreadable locks, and a reclaim lock
50
+ left by a crashed reclaimer are never removed automatically (the error
51
+ names them). The index is written through an exclusively created random
52
+ temp file plus atomic rename while the lock is held, so parallel logins,
53
+ `sync-credential set`, and `remove` never drop each other's entries;
54
+ target identity lowercases only scheme and host (paths keep their case);
55
+ keychain labels are sanitized and keys outside the keychain-safe charset
56
+ map to a digest account, so any project name can be stored; under the
57
+ default `auto` policy a failed keychain write (headless session, locked
58
+ keychain, missing Secret Service) falls back to the file store with a
59
+ printed warning instead of losing a one-time claim. `login` bounds every
60
+ network wait (start, polls, body reads) by `--poll-timeout`.
61
+ - `login` is the one recommended connection path (D-356): help lists it
62
+ right after `init`, `init` and missing-token errors point only at it, and
63
+ `connect-hosted` on a terminal starts the browser sign-in when you press
64
+ Enter at its token prompt. Dashboard tokens, `--token-stdin`,
65
+ `sync-credential`, and the env-var override remain for CI, scripts, and
66
+ browserless machines and are labelled advanced.
67
+
3
68
  ## 0.14.0 - 2026-09-23
4
69
 
5
70
  - Add `continue-session [<lane-id>]` (D-353): resume an already-open lane
package/README.md CHANGED
@@ -243,7 +243,22 @@ maintenance tied to the current lane.
243
243
  ## Hosted Sync
244
244
 
245
245
  Use hosted sync when you want browser review, team workflows, or hosted
246
- docs-review proposals:
246
+ docs-review proposals. The quickest path signs you in from the terminal and
247
+ keeps the token in your OS keychain (or a private per-user file), so it works
248
+ in every new terminal and in agents launched from a desktop app:
249
+
250
+ ```bash
251
+ npx -y @vibecompass/vibecompass@latest login --root .compass
252
+ # opens vibecompass.dev, you confirm a short code and pick the project,
253
+ # the token is stored locally, and the hosted binding is written to project.yaml
254
+
255
+ npx -y @vibecompass/vibecompass@latest push --root .compass
256
+ ```
257
+
258
+ Advanced (CI, scripts, a machine without a browser, or a hosted-only demote):
259
+ bind the root with a dashboard-created token, pasted at the hidden prompt or
260
+ piped in. On a terminal, pressing Enter at that prompt starts the browser
261
+ sign-in instead:
247
262
 
248
263
  ```bash
249
264
  npx -y @vibecompass/vibecompass@latest connect-hosted \
@@ -251,8 +266,12 @@ npx -y @vibecompass/vibecompass@latest connect-hosted \
251
266
  --sync-api-url https://vibecompass.dev \
252
267
  --sync-project-id vc_proj_example \
253
268
  --sync-credential-env-var VIBECOMPASS_SYNC_TOKEN
269
+ # "Paste the sync token from the dashboard (input hidden)"
254
270
 
255
- npx -y @vibecompass/vibecompass@latest push --root .compass
271
+ # non-interactive:
272
+ printf '%s' "$TOKEN" | npx -y @vibecompass/vibecompass@latest connect-hosted --root .compass \
273
+ --sync-api-url https://vibecompass.dev --sync-project-id vc_proj_example \
274
+ --sync-credential-env-var VIBECOMPASS_SYNC_TOKEN --token-stdin
256
275
  ```
257
276
 
258
277
  After `close-session`, run `push` again when a connected local-primary root
@@ -260,16 +279,29 @@ changed canonical project-memory files and the hosted dashboard should catch
260
279
  up. Hosted-only projects do not use a local authoritative push; update or
261
280
  refresh them through the hosted dashboard/proposal flow.
262
281
 
263
- The sync token is read from the environment variable you bind (for example
264
- `VIBECOMPASS_SYNC_TOKEN`). One-off `export`s do not survive new terminals —
265
- persist the token in your shell profile (`~/.zshenv` or `~/.bashrc`):
282
+ ### Where the token lives (D-355)
283
+
284
+ Hosted commands look for the token in this order:
285
+
286
+ 1. the environment variable named in `project.yaml` (`VIBECOMPASS_SYNC_TOKEN`
287
+ by default) — a per-shell override for CI and scripts;
288
+ 2. the local credential store, keyed by hosted URL + project id: the OS
289
+ keychain when available (macOS Keychain, Linux `secret-tool`), otherwise
290
+ `~/.config/vibecompass/credentials.json` (`0600`; `%APPDATA%\vibecompass`
291
+ on Windows; `VIBECOMPASS_CONFIG_DIR` overrides the location).
292
+
293
+ The token value is never written to `project.yaml`, `state/`, or any file in
294
+ your repo. Manage stored tokens with:
266
295
 
267
296
  ```bash
268
- echo 'export VIBECOMPASS_SYNC_TOKEN="<your sync token>"' >> ~/.zshenv
297
+ npx -y @vibecompass/vibecompass@latest sync-credential list --root .compass
298
+ npx -y @vibecompass/vibecompass@latest sync-credential set --root .compass # hidden prompt, --token-stdin, or --from-env
299
+ npx -y @vibecompass/vibecompass@latest sync-credential remove --root .compass
269
300
  ```
270
301
 
271
- If the token is lost, rotate it on the hosted dashboard under Setup -> Hosted
272
- sync and export the new value.
302
+ `vibecompass status` shows which source is in use (never the value). Lost a
303
+ token? Run `login` again, or create a new one on the dashboard under Setup ->
304
+ Hosted sync and revoke the old one there.
273
305
 
274
306
  ### Multiple environments
275
307
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibecompass/vibecompass",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Local-first project-memory core for VibeCompass",
5
5
  "type": "module",
6
6
  "bin": {