@functional-systems/lambdadb-cli 0.1.6 → 0.1.7-dev.24

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/CONTRIBUTING.md +29 -0
  3. package/DESIGN.md +9 -3
  4. package/ONBOARDING.md +417 -0
  5. package/README.md +390 -138
  6. package/dist/account.d.ts +50 -0
  7. package/dist/account.js +301 -0
  8. package/dist/account.js.map +1 -0
  9. package/dist/agent-config.d.ts +4 -3
  10. package/dist/agent-config.js +12 -5
  11. package/dist/agent-config.js.map +1 -1
  12. package/dist/agents.d.ts +3 -3
  13. package/dist/agents.js +8 -8
  14. package/dist/agents.js.map +1 -1
  15. package/dist/cli.js +44 -6
  16. package/dist/cli.js.map +1 -1
  17. package/dist/config.d.ts +10 -4
  18. package/dist/config.js +43 -6
  19. package/dist/config.js.map +1 -1
  20. package/dist/credentials.d.ts +29 -0
  21. package/dist/credentials.js +116 -0
  22. package/dist/credentials.js.map +1 -0
  23. package/dist/device-auth.d.ts +16 -0
  24. package/dist/device-auth.js +160 -0
  25. package/dist/device-auth.js.map +1 -0
  26. package/dist/errors.d.ts +7 -0
  27. package/dist/errors.js +35 -1
  28. package/dist/errors.js.map +1 -1
  29. package/dist/init.d.ts +5 -2
  30. package/dist/init.js +50 -31
  31. package/dist/init.js.map +1 -1
  32. package/dist/mcp.js +8 -1
  33. package/dist/mcp.js.map +1 -1
  34. package/dist/projects.d.ts +29 -0
  35. package/dist/projects.js +323 -0
  36. package/dist/projects.js.map +1 -0
  37. package/package.json +7 -2
  38. package/skills/lambdadb/SKILL.md +9 -6
  39. package/src/account.ts +351 -0
  40. package/src/agent-config.ts +14 -8
  41. package/src/agents.ts +8 -8
  42. package/src/cli.ts +46 -6
  43. package/src/config.ts +43 -10
  44. package/src/credentials.ts +138 -0
  45. package/src/device-auth.ts +200 -0
  46. package/src/errors.ts +31 -2
  47. package/src/init.ts +42 -29
  48. package/src/mcp.ts +7 -1
  49. package/src/projects.ts +439 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Added
6
+
7
+ - Browser-approved `init --connect`, including another-device URLs for SSH, shared
8
+ Console signup/login, terminal project setup, bounded polling and explicit key issuance.
9
+ - Separate OS-stored account login with seven-day expiry, immediate logout, and
10
+ reusable `orgs list` / `projects list|regions|create|use` commands. Org-specific
11
+ billing guidance uses current backend limits. Project switching reuses saved
12
+ keys and keeps existing agent connections pinned.
13
+ - OS credential references for macOS Keychain, Windows Credential Manager and
14
+ Linux Secret Service with a new-connection keyutils fallback. Plaintext files
15
+ and agent arguments never contain keys. Preserve the existing environment/CI path.
16
+ - Resume agent setup with the saved connection, and remove local OS credentials
17
+ with `credentials remove` without revoking server keys.
18
+
19
+ ### Maintenance
20
+
21
+ - Prevent inherited npm exec package/command selectors from changing the nested
22
+ MCP launch, including when the CLI is invoked through `npx --package`.
23
+
24
+ - Synchronize the 0.1.6 release history and start the 0.1.7 development line.
25
+ - Update the Homebrew formula to verified stable 0.1.6.
26
+
5
27
  ## [0.1.6] - 2026-10-25
6
28
 
7
29
  ### Maintenance
package/CONTRIBUTING.md CHANGED
@@ -216,3 +216,32 @@ signed URLs. Historical repository records remain available through Git history.
216
216
  Do not append per-run logs, release-status snapshots or successful test counts to
217
217
  maintainer guides. A completed verification does not require another documentation
218
218
  PR. Update these guides when procedures, requirements or supported behavior change.
219
+
220
+ ### Native credential validation
221
+
222
+ `npm test` uses synthetic in-memory stores and loopback authorization responses;
223
+ it does not claim an actual OS store or account login worked. To exercise the
224
+ current OS store with a unique synthetic key, a fresh-process doctor against a
225
+ loopback server, a simulated MCP child, and separate account-session retrieval
226
+ from a fresh management process:
227
+
228
+ ```sh
229
+ npm run build
230
+ LAMBDADB_TEST_NATIVE_CREDENTIALS=1 node --test test/native-credentials.test.mjs
231
+ # Linux may explicitly select either backend:
232
+ LAMBDADB_TEST_NATIVE_CREDENTIALS=1 LAMBDADB_TEST_CREDENTIAL_STORE=secret-service node --test test/native-credentials.test.mjs
233
+ ```
234
+
235
+ The opt-in tests remove their credentials in `finally`. The Windows path checks the
236
+ store and doctor but skips the POSIX fake-npx child. Run the kernel-keyutils check
237
+ on a host that permits keyring syscalls; default Docker isolation may not. A
238
+ missing/locked native backend must never make the environment path unavailable.
239
+ See [ONBOARDING.md](ONBOARDING.md) for the cross-repository contract and rollout.
240
+
241
+ Account/project tests use separate synthetic credential namespaces and loopback
242
+ management responses. Run `node --test test/account.test.mjs` after building for
243
+ focused coverage of secret-free metadata, explicit issuance, saved-key switching,
244
+ concurrent edits, symlink aliases, quota guidance and non-interactive failures.
245
+ The package check runs these tests against the installed tarball as well. Backend
246
+ PostgreSQL tests and Console browser tests are documented in their repositories;
247
+ no simulated session is evidence of live signup, provisioning or billing.
package/DESIGN.md CHANGED
@@ -147,8 +147,12 @@ CLI arguments/configuration → input validation → SDK facade → LambdaDB API
147
147
  ```
148
148
 
149
149
  - `cli.ts`: command tree, target selection, SDK calls and process exit codes.
150
- - `config.ts`: deterministic user-local configuration, environment auth and
150
+ - `config.ts`: deterministic user-local configuration, OS/environment credential resolution and
151
151
  atomic non-secret settings writes.
152
+ - `credentials.ts`: explicit native OS store selection and verified credential writes.
153
+ - `device-auth.ts`: bounded control-plane device authorization; never retries uncertain issuance.
154
+ - `account.ts`: isolated OS account sessions, bounded management requests and local metadata locking.
155
+ - `projects.ts`: terminal Org/project setup, current-limit guidance and cached project selection.
152
156
  - `input.ts`: bounded file snapshots, strict request preflight, SDK serializer
153
157
  reuse and the small null-size compatibility adjustment.
154
158
  - `import-workflow.ts`: byte/count batching, sequential submission, honest
@@ -157,7 +161,9 @@ CLI arguments/configuration → input validation → SDK facade → LambdaDB API
157
161
  - `errors.ts` and `output.ts`: safe error classification, versioned output and
158
162
  credential redaction.
159
163
 
160
- There is no second HTTP implementation, separate workflow package, plugin system
164
+ Project data requests remain SDK-only. Device authorization and project management use a small, bounded
165
+ control-plane JSON client because the project SDK has no account authorization API.
166
+ There is no separate workflow package, plugin system
161
167
  or SDK fork. `listCollectionsPages` owns pagination. `bulkUpsertDocs` owns upload
162
168
  metadata, signed PUT, server-provided byte limit and finalization. Query/fetch
163
169
  helpers own presigned response downloads and authentication isolation.
@@ -167,7 +173,7 @@ helpers own presigned response downloads and authentication isolation.
167
173
  | Decision | Reason |
168
174
  | --- | --- |
169
175
  | Mandatory endpoint/project resolution, explicit collection, read ref and write branch | Avoid SDK playground/main fallbacks silently choosing a target. |
170
- | Environment-held keys only | Keeps secrets out of argv and repository/user configuration files. |
176
+ | OS-store references or environment-held project keys | Account login and browser setup use the OS credential store; manual/CI setup can select an environment variable. Configuration contains only non-secret references, never key values or tokens; no plaintext fallback. |
171
177
  | Read retry policy bounded through SDK, no mutation retries | No public exactly-once or mutation receipt contract; a missing reply cannot prove rejection. |
172
178
  | Entire JSONL preflight before writes | A malformed later line must not unexpectedly leave accepted earlier batches. |
173
179
  | 64 MiB / 100,000-document input caps, 4 MB ordinary batches, configurable bulk batches | Bound file size and retained row overhead without building streaming/checkpoint infrastructure; scan lines without a full split array. |
package/ONBOARDING.md ADDED
@@ -0,0 +1,417 @@
1
+ # Unified onboarding plan
2
+
3
+ Discussion recorded on 2026-10-26. This is a cross-repository implementation plan,
4
+ not a description of released behavior. Agreed product direction is separated
5
+ from the implementation contract below. The work is not deployed or published.
6
+
7
+ The next scope connects signup, Organization selection or creation, project setup,
8
+ and CLI authorization. Console and CLI users share the same account and project
9
+ onboarding; their completion steps differ. The existing CLI package, executable,
10
+ agent adapters, skill, and stdio MCP integration remain the foundation.
11
+
12
+ ## Terminal project management
13
+
14
+ Browser authorization grants a separate CLI account session. Browser signup/login and deliberate CLI
15
+ approval return an account session; Org/project selection and creation happen in
16
+ the terminal. `login`, `logout`, `orgs list`, `projects list`, `projects create`,
17
+ `projects regions`, and `projects use` are maintained commands reused by `init`.
18
+
19
+ Account sessions are stored separately in the OS credential store, never in
20
+ project configuration or MCP arguments/environment. The initial session lifetime
21
+ is seven days, matching the existing Console session horizon; explicit login
22
+ renews authorization. Server-side hashed sessions are checked on each management
23
+ request and logout revokes them immediately. These credentials authenticate only
24
+ new CLI management routes; existing member-JWT routes and project APIs retain
25
+ their authentication boundaries. Project keys remain independently usable after
26
+ account logout. Account deletion/inactivation disables CLI management access.
27
+
28
+ The server's actual Org project count/limit governs creation. At the limit,
29
+ interactive init offers an existing project first, an Org-specific Console
30
+ billing link, or cancel. Only an Org owner can activate billing. Paid/custom
31
+ limits are not hard-coded. After billing, re-read server state before retrying;
32
+ non-interactive commands return a structured limit error and actionable link.
33
+ Billing remains entirely in Console. The billing entry page validates membership
34
+ and explicitly confirms the target Org before switching browser context.
35
+
36
+ Project selection reuses saved per-project credentials. New key issuance requires
37
+ an explicit choice, uses a unique request identity, and never retries an uncertain
38
+ write. `projects use` changes the CLI default only: existing agent entries stay
39
+ pinned until the user reruns agent setup. Ordinary management commands do not
40
+ prompt; only explicit login waits for browser authorization and init asks setup
41
+ questions. No deletion, billing mutation, or member management is added to CLI.
42
+
43
+ ## Agreed product direction
44
+
45
+ - Apply the simplified onboarding to both direct Console signup and entry through
46
+ `lambdadb init`, including `npx @functional-systems/lambdadb-cli@latest init`.
47
+ Keep the existing npm package and executable.
48
+ - Use **Organization** or **Org** consistently. Do not introduce Workspace as a
49
+ second name for the same product concept.
50
+ - For a user without an existing Org or a pending invitation, create a default
51
+ Org when they submit their first project creation. Signing in alone does not
52
+ create an Org. Existing users select an accessible Org; preserve invitation
53
+ handling before offering a default Org.
54
+ - Generate the default Org display name from the signup display name, for
55
+ example `Steven's Organization`, with `My Organization` as the fallback.
56
+ Do not use the full email address as the default name. Allow renaming later;
57
+ the display name must not become the authorization identity.
58
+ - Show the destination Org in the project creation screen. Remove the separate
59
+ required Org naming step, while retaining project name and region selection.
60
+ - Make the role, team size, and industry survey optional and move it after
61
+ successful setup. An unanswered survey must not block either entry path or
62
+ cause a redirect loop. Preserve existing signup verification and required
63
+ consent; survey completion is a separate concern.
64
+ - Defer new server-enforced read-only key permissions and key-expiration features.
65
+ Preserve the existing MCP tool defaults and explicit write-tool opt-in. Tool
66
+ visibility is not a server-side restriction on the project API key.
67
+ - Defer remote MCP. Use the existing stdio MCP package for this scope.
68
+
69
+ ## Shared user flow
70
+
71
+ | Step | Shared behavior | Direct Console entry | CLI entry |
72
+ | --- | --- | --- | --- |
73
+ | Entry | Retain a validated continuation through signup and login. | Start from the website or Console. | Start from the existing init command. |
74
+ | Identity | Reuse Google or email verification and existing required consent. | Continue in Console. | Authorize using a browser, including a browser on another device. |
75
+ | Org | Handle invitations and accessible Orgs before creating a default Org. | Show the same Org choices and defaults. | Show the same Org choices and defaults. |
76
+ | Project | Select an accessible project or explicitly create one with a name and region. Enforce existing roles, billing, and quotas. | Finish on the selected project's Console page. | Select/create in the terminal after account login, then explicitly issue or reuse a project key. |
77
+ | Connection | Use the selected project's endpoint and identity. | Keep normal Console navigation. | Store separate account/project credentials in the OS store, then configure agents with only project references. |
78
+ | Completion | Offer the optional survey without blocking use. | Show project setup guidance. | Verify authentication and collection-list access, show reload instructions, and provide an actionable next step. |
79
+
80
+ Only create a project after the user submits its creation. Do not create a
81
+ collection or insert sample documents during onboarding. A successful connection
82
+ or doctor check does not establish search readiness. For an existing collection,
83
+ guide the user to inspect its fields before forming a search. For an empty
84
+ project, explain the next deliberate data setup step.
85
+
86
+ Project provisioning may remain pending. Use a bounded wait with a resumable
87
+ status and an actionable next step; do not report a project as ready for key
88
+ issuance or searches merely because its creation request succeeded.
89
+
90
+ ### CLI authorization flow
91
+
92
+ Prefer a device authorization flow based on
93
+ [RFC 8628](https://www.rfc-editor.org/rfc/rfc8628). Print an HTTPS verification
94
+ URL and a user code so SSH and remote development users can approve in a browser
95
+ on another device. Opening a browser on the CLI host may be a convenience, but
96
+ must not be required. The selected contract is documented below.
97
+
98
+ The browser shows the code, current account, seven-day lifetime and requested
99
+ management access before approval. The terminal subsequently shows the selected
100
+ Org, project and key-issuance choice. Bind the resulting
101
+ grant to the initiating session, enforce expiry and single consumption, and support denial,
102
+ cancellation, and bounded polling. Never place project keys or account tokens in
103
+ browser URLs. Validate continuation destinations and retain them across Google
104
+ callbacks, email verification, invitations, and project creation.
105
+
106
+ CLI authorization is independent of remote MCP OAuth. Implementing this flow
107
+ does not require hosting a new MCP service.
108
+
109
+ ## Agreed credential storage policy
110
+
111
+ The existing environment mode stores endpoint, project, and the API-key environment
112
+ variable name. It reads the secret at runtime; it does not save key values.
113
+ See [configuration](src/config.ts), [init](src/init.ts), and the
114
+ [stdio bridge](src/mcp.ts).
115
+
116
+ The following extension was agreed on 2026-10-26 for the browser flow:
117
+
118
+ - Use an available OS credential store by default for the project API key. Keep
119
+ a non-secret connection reference in CLI and agent configuration.
120
+ - Resolve that reference inside the CLI stdio bridge and supply the key only to
121
+ the MCP child process. Continue mapping the CLI's credential source to
122
+ `LAMBDADB_PROJECT_API_KEY`, with the selected endpoint and project mapped to
123
+ `LAMBDADB_BASE_URL` and `LAMBDADB_PROJECT_NAME`.
124
+ - Keep account login credentials separate from project API keys. Do not forward
125
+ member access tokens, refresh tokens, or backend administration keys to agents
126
+ or the MCP child. Account login uses a separate opaque seven-day session in the
127
+ OS store; no Console JWT or refresh token is persisted by CLI.
128
+ - Preserve the environment-variable path for existing users, CI, and headless
129
+ environments. Define precedence before adding a second credential source.
130
+ - For a new Linux connection, prefer Secret Service, then use the kernel keyutils
131
+ store when Secret Service is unavailable. Show the selected store and explain
132
+ that kernel-cached credentials may require reconnection after reboot or expiry.
133
+ If neither OS store is available, provide an actionable environment-based path.
134
+ Do not silently fall back to plaintext storage. A separate file-based secret
135
+ storage mode is outside the first version.
136
+ - Keep secrets out of command arguments, logs, JSON output, project files,
137
+ skills, and agent configuration. Document credential removal and distinguish
138
+ local removal from server-side key revocation.
139
+
140
+ The implemented contract below fixes library selection, credential precedence,
141
+ grant lifetime and local removal. Public documentation now distinguishes OS
142
+ credential persistence from secret-free CLI and agent configuration. These changes
143
+ remain unreleased until the coordinated rollout is approved.
144
+
145
+ ### Operating system targets
146
+
147
+ | Environment | Credential storage target | Availability requirement |
148
+ | --- | --- | --- |
149
+ | macOS | Keychain | The CLI and agent-launched bridge can access the user's keychain. |
150
+ | Linux desktop | Secret Service first, then kernel keyutils | Secret Service needs a reachable user D-Bus session and an accessible collection; kernel fallback needs working keyring access. |
151
+ | Windows | Windows Credential Manager | The credential store is accessible in the user context running the CLI and agent. |
152
+ | Linux over SSH, containers, and WSL | Secret Service where available, then kernel keyutils, then environment variables | Do not assume a desktop session, kernel keyring permission, or access to the host OS store. |
153
+ | CI | Existing environment-variable path | Non-interactive operation must not require browser approval or an unlocked desktop store. |
154
+
155
+ These are implementation targets, not a claim of tested LambdaDB support. Native
156
+ packaging and real credential operations must be verified on each supported OS
157
+ and architecture, including access from an agent-launched process.
158
+
159
+ The [keyring library documentation](https://docs.rs/keyring/3.6.3/keyring/)
160
+ describes the macOS, Windows, and Linux store types.
161
+ [`@napi-rs/keyring`](https://github.com/Brooooooklyn/keyring-node#linux-backend-selection)
162
+ is the selected Node binding. Linux fallback to kernel keyutils is allowed
163
+ for a new connection. Record the selected backend in the non-secret connection
164
+ metadata so later reads address the same store instead of silently switching.
165
+ The implementation pins optional `@napi-rs/keyring` 2.1.2 and explicitly selects
166
+ the Linux backend. The optional dependency is loaded only when OS storage is used.
167
+
168
+ Kernel keyutils is an OS-managed cache. CLI exit alone does not necessarily clear
169
+ it, but reboot or keyring expiry can remove the credential. Explain this in the
170
+ setup result. If a saved credential becomes unavailable, keep the connection
171
+ metadata and guide the user through explicit reconnection; do not silently issue
172
+ another project key. Non-interactive commands return an actionable error.
173
+ An unreadable or locked existing store must not be treated as a new connection
174
+ eligible for automatic fallback. Cache loss does not revoke the server-side API
175
+ key; retain its identity for deliberate replacement or cleanup. See the
176
+ [keyutils persistence contract](https://docs.rs/linux-keyutils-keyring-store/1.0.0/linux_keyutils_keyring_store/#persistence).
177
+
178
+ ### Key issuance and recovery
179
+
180
+ Use the existing project API-key service with its current role checks. A browser
181
+ login must not bypass Org membership or key-management permissions. Approval
182
+ should identify whether a new project key will be issued and where it will be
183
+ kept. Reuse a valid saved connection on reruns instead of minting another key.
184
+
185
+ Project keys are revealed once and active-key limits apply. Define recovery for
186
+ an issued key whose delivery or local save fails. Do not blindly retry key or
187
+ project creation after an ambiguous response. Likewise, if default Org creation
188
+ succeeds but project creation fails, retain and reuse that Org on retry. Handle
189
+ concurrent tabs and repeated submissions without creating duplicate Orgs,
190
+ projects, or keys.
191
+
192
+ ## Repository responsibilities
193
+
194
+ | Repository | Planned responsibility |
195
+ | --- | --- |
196
+ | `lambdadb-console` | Shared signup routing, optional survey, default Org guidance, project selection or creation, CLI authorization screen, and continuation handling. |
197
+ | `lambdadb-backend` | Default Org creation and recovery semantics, CLI authorization lifecycle, project access checks, and controlled delivery of a project credential. Reuse project provisioning and key services. |
198
+ | `lambdadb-cli` | Browser authorization entry and polling, credential resolution, resumable init, existing configuration and doctor reuse, stdio credential forwarding, agent previews, skill installation, and completion guidance. |
199
+ | `lambdadb-fe` | Adjust signup links or entry copy only where required. Account and project onboarding stays in Console. |
200
+ | `lambdadb-mcp` | Reuse the existing stdio package. Change it only if an actual integration gap is established. |
201
+ | `lambdadb` | No data-engine change is currently planned. Server-enforced key write restrictions and expiration are deferred. |
202
+
203
+ The four prepared implementation worktrees use `feat/unified-onboarding`, based
204
+ on each repository's `origin/develop`. Keep implementation in those worktrees.
205
+ This plan stays in the CLI repository as the shared reference; do not copy it
206
+ into the other repositories and maintain divergent versions.
207
+
208
+ ## Implementation order
209
+
210
+ 1. **Finalize contracts.** Define the default Org naming and creation behavior,
211
+ invitation precedence, authorization state machine, credential storage and
212
+ precedence, provisioning timeout, and recovery after an ambiguous write.
213
+ Review the existing authentication surface and the protection and deployment
214
+ exposure of token-generation routes before extending authentication.
215
+ 2. **Simplify shared onboarding.** Implement the common Org and project flow in
216
+ Backend and Console. Remove survey-based blocking from all login and signup
217
+ paths. Verify direct UI entry and existing-user and invitation behavior first.
218
+ 3. **Connect an existing project from CLI.** Add the browser approval flow,
219
+ credential resolution, and handoff to the existing init implementation.
220
+ Verify the complete flow using an existing development project before adding
221
+ project creation to the CLI continuation.
222
+ 4. **Complete new-user setup.** Carry CLI continuation through signup, default
223
+ Org creation, project creation, and provisioning. Add only the necessary FE
224
+ link changes and test recovery and reruns across these boundaries.
225
+ 5. **Validate and document rollout.** Update CLI help and credential documentation,
226
+ Console guidance, API documentation, and relevant release notes. Keep each PR
227
+ coherent and record cross-repository dependencies and deployment order.
228
+
229
+ The grant and storage integration details below are implemented locally.
230
+ Backend contracts should be available before dependent Console or CLI behavior
231
+ is enabled; an unready server must produce an actionable failure rather than a partially successful
232
+ setup. Existing manual Console key setup remains supported during rollout.
233
+
234
+ ## Implemented contract and rollout
235
+
236
+ - `POST /auth/device/login` returns a 256-bit device code, 50-bit displayed user
237
+ code, configured Console verification URL, 15-minute expiry and five-second
238
+ polling interval. The backend stores code hashes only, with a maximum of 1,024
239
+ unexpired grants across replicas. Per-process IP limits complement that bound.
240
+ - JWT-only `/auth/device/inspect` and `/auth/device/decision` support explicit
241
+ browser approval/denial. Approval binds only the member and never creates an
242
+ Org, project or project key. Key issuance is a separate, explicit management
243
+ request with owner/admin and readiness checks reused from project key management.
244
+ - The device grant is marked consumed before account-session creation.
245
+ Project-key requests are separately claimed before external issuance. Neither the backend
246
+ nor CLI blindly retries uncertain issuance. Redemption returns an
247
+ opaque CLI session once, not a Console JWT. No raw account token or project key
248
+ is persisted in the database and no secret is sent in a browser URL. The former
249
+ unauthenticated developer `/auth/generate` route and its unused implementation are removed before enabling this flow.
250
+ - New project keys use a fresh OS entry, bound to endpoint/project and a UUID.
251
+ Save/readback must match. Settings retain store, entry UUID, key ID and key name.
252
+ Existing slots are never overwritten or silently migrated. `credentials remove`
253
+ deletes the current local entry without revoking the server key.
254
+ - `init --connect` resumes terminal Org/project selection using a saved login
255
+ and reuses per-project keys. Issuing a new or replacement key is explicit.
256
+ On a first run, interactive init offers browser or environment setup. SSH uses `--no-browser`; automation uses
257
+ existing credentials with `--non-interactive --agents ... --scope ...`.
258
+ - Browser setup previews the CLI settings path/store and saves a successfully
259
+ delivered connection before doctor/agent installation. This intentionally lets
260
+ a failed doctor or agent install resume without issuing another key. Agent file
261
+ plans are separately displayed and confirmed before applying them. A saved
262
+ connection is not evidence that collection-list access or search is ready.
263
+ - CLI management routes under `/auth/cli` accept only a hashed, revocable
264
+ seven-day account session. A member may hold up to 20 live sessions; explicit
265
+ login replaces the selected local session after the new one is durable.
266
+ `/connect` claims a request UUID before issuance and retains the claim for
267
+ seven days, bounded to 1,000 claims per member. These bounds are server abuse
268
+ controls, not plan/project limits. Existing project-key limits still apply.
269
+ - `projects create` reuses project validation/provisioning and Org-row quota
270
+ locking. It does not issue a CLI project key, select the CLI default or touch
271
+ agents. `projects use --issue-key` is the explicit issuance command. Project
272
+ selection without that flag reads a saved reference and never mints a key.
273
+ - Non-secret `config.json.account.json` and `config.json.connections.json`
274
+ sidecars follow the resolved `--config` destination. Account slots use a
275
+ separate OS service namespace that the MCP bridge cannot resolve. A local
276
+ exclusive management lock prevents overlapping login/selection writes.
277
+ Configuration edits are checked before replacement; completed connections
278
+ remain cached when later settings/doctor/agent work fails.
279
+ - Console carries only validated local continuations across signup, verification,
280
+ invitations and project setup. Default Org creation and invitation decisions
281
+ serialize on the member; project creation serializes quota checks on the Org.
282
+ An optional survey never gates access. The old placeholder project page redirects
283
+ to the real shared flow. Existing FE redirects already preserve these paths and
284
+ queries; no FE, engine or MCP package changes are required for this contract.
285
+ - Provisioning UI checks for ten minutes, offers manual refresh, and can resume an
286
+ existing project after device expiry. Ambiguous project creation requires
287
+ checking Console and possibly operational reconciliation; distributed project
288
+ creation is not claimed to be an atomic transaction.
289
+
290
+ Deploy Backend first with `deviceAuthorization.enabled` false, then Console.
291
+ Set `deviceAuthorization.consoleURL` to that Console's exact origin and enable
292
+ routes for a designated development acceptance run. Only then publish the CLI
293
+ through its existing release process with separate authorization. Disabling the
294
+ device routes rolls back new authorization without revoking existing project keys.
295
+ The grant, CLI-session and key-request tables are additive. Existing environment setup works throughout.
296
+
297
+ Native implementations target macOS, Linux and Windows. The maintained opt-in
298
+ credential test exercises actual OS storage and a fresh-process doctor/bridge;
299
+ unit tests alone do not establish native support. Windows and kernel-keyutils
300
+ success require environments that actually provide those facilities. Default
301
+ Docker restrictions can make keyutils unavailable; the correct result is an
302
+ actionable environment-mode fallback, never a plaintext file.
303
+
304
+ ## Acceptance and verification
305
+
306
+ - Both UI and CLI entry support a new user, an existing user, multiple Orgs,
307
+ pending invitations, and an unanswered survey. Default Org naming is editable;
308
+ reruns and concurrent submissions preserve a single intended Org and project.
309
+ - Browser approval supports a separate device and covers denial, expiry,
310
+ cancellation, invalid continuations, consumed grants, and a terminal that
311
+ disconnects. Preserve authentication and key-management role checks.
312
+ - Cover project quota rejection, unavailable regions, pending provisioning,
313
+ failed project creation after Org creation, failed key delivery or storage,
314
+ revoked keys, and unavailable credential stores.
315
+ - Verify Linux Secret Service preference, kernel fallback with a visible lifetime
316
+ notice, unavailable kernel access, and reconnect behavior after cache loss.
317
+ Existing connections must keep using their recorded backend, and cache loss
318
+ must not cause silent key issuance or server-side revocation.
319
+ - Preserve unrelated agent configuration, show every destination file and scope
320
+ before changes, and keep reruns safe. Verify that credentials do not enter
321
+ generated files or diagnostics. Explain agent restart or reload requirements.
322
+ - Keep existing commands non-interactive. Document explicit non-interactive init
323
+ inputs and actionable failures. Missing credentials or approval must not open
324
+ a browser, wait indefinitely, silently create resources, or claim success in
325
+ that path.
326
+ - Reuse authentication and collection-list verification. Report connection
327
+ success separately from data availability, indexing, and search readiness.
328
+
329
+ For CLI implementation, use the checks in [CONTRIBUTING.md](CONTRIBUTING.md):
330
+ `npm ci`, `npm run lint`, `npm run check:version`, `npm run typecheck`, `npm test`,
331
+ and `npm run test:package`. Verify the installed tarball and both invocation
332
+ forms, not only execution from source. Follow each sibling repository's current
333
+ instructions and CI configuration for its implementation checks.
334
+
335
+ Record mock and loopback checks separately from actual browser login,
336
+ live-service access, OS credential-store behavior, and native agent startup.
337
+ Use designated development resources for live verification and track cleanup.
338
+ Do not publish packages, deploy services, or merge PRs as a consequence of local
339
+ validation; those actions remain separately authorized.
340
+
341
+ ## Reference behavior
342
+
343
+ Neon provides a useful UX reference, rather than a requirement to copy its
344
+ storage policy or remote MCP architecture. Its current
345
+ [login documentation](https://neon.com/docs/cli/login) describes local
346
+ `credentials.json` storage and an optional `--keyring` mode. Its
347
+ [MCP documentation](https://neon.com/docs/cli/mcp) describes API keys written into
348
+ agent configuration or OAuth sign-in by the agent. Its
349
+ [init documentation](https://neon.com/docs/cli/init) describes project linking
350
+ and agent setup. These are separate credential paths; selecting a CLI keyring
351
+ does not imply that agent API keys use that store.
352
+
353
+ ### Neon implementation review
354
+
355
+ Reviewed on 2026-10-26 at
356
+ [`7d1a2a7`](https://github.com/neondatabase/neon-pkgs/tree/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli),
357
+ whose CLI package version is 8.11.3. The credential implementation spans
358
+ `packages/cli` and `internals/cli-core`.
359
+
360
+ - **Native binding and packaging.** Neon pins `@napi-rs/keyring` 1.3.0 as an
361
+ optional dependency and loads it lazily. Its adapter returns unavailable when
362
+ the native module cannot load or when running a `pkg` standalone binary.
363
+ Windows values are limited to 1280 UTF-16 code units before writing.
364
+ LambdaDB should keep environment-only commands and help usable without the
365
+ addon, and validate native loading in the installed npm/npx and Homebrew
366
+ artifacts. Store a compact project-key payload and check platform size limits.
367
+ Sources: [package manifest](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/package.json),
368
+ [keyring adapter](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/src/keyring.ts).
369
+ - **OS selection.** The pinned binding uses macOS Keychain and the Windows
370
+ native credential store. On Linux it tries Secret Service, then kernel
371
+ keyutils if store initialization fails. Neon does not override that selection.
372
+ LambdaDB adopts this fallback order for new connections and adds a visible
373
+ lifetime notice and a recorded backend. The candidate binding's 2.1.2 API
374
+ supports explicitly selecting either store, which allows subsequent reads to
375
+ use the recorded backend. The implementation selects that version.
376
+ Kernel keyutils does not retain credentials across a reboot.
377
+ Sources: [1.3.0 OS setup](https://github.com/Brooooooklyn/keyring-node/blob/e46be75c3ba8d5fde6b88a17c6153b87ffe4b946/src/entry.rs),
378
+ [1.3.0 Linux fallback](https://github.com/Brooooooklyn/keyring-node/blob/e46be75c3ba8d5fde6b88a17c6153b87ffe4b946/src/linux_credential_builder.rs),
379
+ [2.1.2 explicit store selection](https://github.com/Brooooooklyn/keyring-node/blob/52184fbebffeef8a061234f60f313c479b954f9f/README.md#linux-backend-selection).
380
+ - **Credential identity and errors.** Neon's shared store isolates entries by
381
+ service, a hash of the resolved configuration directory, and profile name.
382
+ It treats null reads as potentially locked or denied, rather than proving that
383
+ a key is absent. LambdaDB uses a small credential-store interface with a fresh
384
+ UUID for each connection, bound to endpoint/project across CLI and agent
385
+ launches. Copies of the same non-secret reference intentionally address the
386
+ same OS entry. An unreadable entry
387
+ must not trigger automatic replacement or key issuance.
388
+ Source: [credential store](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/internals/cli-core/src/credential_store.ts).
389
+ - **Saving and removing credentials.** Neon reads after writing and can restore
390
+ a readable previous value on failure. Its read-back check tests for a non-null
391
+ result; LambdaDB should also compare the saved value before committing the
392
+ configuration reference. Neon distinguishes confirmed deletion from an
393
+ unreadable or remaining item. Preserve that distinction in user-facing results.
394
+ Local removal and server revocation remain separate outcomes. Its replacement
395
+ logic retires an old credential only after saving the replacement and avoids
396
+ revoking the same key or an imported key without recorded issuance metadata.
397
+ LambdaDB saves a fresh slot on explicit reconnection and retains older entries
398
+ for agents that still reference them. Cleanup and server revocation remain
399
+ explicit; ordinary reruns reuse the working connection.
400
+ Sources: [store write and delete behavior](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/internals/cli-core/src/credential_store.ts),
401
+ [credential retirement](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/src/retire_credential.ts).
402
+ - **Storage policy.** Neon's login selects file storage by default and remembers
403
+ a profile's explicit keyring selection. Its MCP API-key path writes a bearer
404
+ key into agent configuration. LambdaDB's agreed policy instead uses the OS
405
+ store by default, environment variables when needed, and secret-free agent
406
+ configuration through the stdio bridge. The expanded implementation also
407
+ persists a separate seven-day CLI account session. Neon's refresh machinery
408
+ is not copied; expiry requires explicit browser reauthorization.
409
+ Sources: [login storage selection](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/src/commands/auth.ts),
410
+ [MCP configuration](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/src/mcp/install.ts).
411
+
412
+ The reviewed [credential-store tests](https://github.com/neondatabase/neon-pkgs/blob/7d1a2a728329be3e11589360b5ea70e1fc8d5857/packages/cli/src/credential_store.test.ts)
413
+ use an in-memory backend to exercise isolation, size limits, unreadable entries,
414
+ failed read-back, deletion outcomes, and redaction. Reuse those distinct test
415
+ cases as design inputs, then separately verify actual OS storage, persistence,
416
+ fresh-process retrieval, and agent access. This review inspected source and
417
+ tests; it did not execute Neon or validate native stores on any OS.