@lanes-sh/link 0.7.2 → 0.8.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/README.md +20 -10
- package/instructions/agents/lanes-link-scout.md +2 -2
- package/instructions/skills/lanes-link/SKILL.md +136 -61
- package/package.json +2 -1
- package/src/audit/index.ts +8 -1
- package/src/auth/index.ts +58 -2
- package/src/auth/lanes/assertion.ts +256 -0
- package/src/auth/lanes/callback.ts +135 -0
- package/src/auth/lanes/federation.ts +50 -0
- package/src/auth/lanes/login.ts +294 -0
- package/src/auth/lanes/members.ts +103 -0
- package/src/auth/lanes/session.ts +97 -0
- package/src/auth/oauth/grant.ts +183 -0
- package/src/auth/oauth/result.ts +27 -0
- package/src/auth/oauth/server.ts +176 -203
- package/src/auth/oauth/store.ts +65 -0
- package/src/auth/remote.ts +32 -9
- package/src/cli/accepts.ts +108 -0
- package/src/cli/argv.ts +57 -3
- package/src/cli/audit-change.ts +140 -0
- package/src/cli/callback-page.ts +36 -115
- package/src/cli/commands/auth-dispatch.ts +48 -0
- package/src/cli/commands/auth.ts +229 -0
- package/src/cli/commands/connect/accounts.ts +4 -4
- package/src/cli/commands/connect/authorise.ts +4 -4
- package/src/cli/commands/connect/bind-credential.ts +2 -1
- package/src/cli/commands/connect/custom/index.ts +1 -1
- package/src/cli/commands/connect/custom/write.ts +2 -2
- package/src/cli/commands/connect/grant.ts +29 -14
- package/src/cli/commands/connect/index.ts +88 -87
- package/src/cli/commands/connect/options.ts +83 -0
- package/src/cli/commands/connect/registration.ts +50 -0
- package/src/cli/commands/connect/requirements.ts +1 -1
- package/src/cli/commands/connect/settle.ts +4 -2
- package/src/cli/commands/connect/target-note.ts +7 -2
- package/src/cli/commands/connect/unknown.ts +1 -1
- package/src/cli/commands/connect/variables.ts +3 -2
- package/src/cli/commands/connection-list.ts +116 -0
- package/src/cli/commands/connection.ts +182 -165
- package/src/cli/commands/grant.ts +140 -0
- package/src/cli/commands/identity.ts +21 -9
- package/src/cli/commands/knowledge/index.ts +46 -79
- package/src/cli/commands/knowledge/migrate.ts +74 -13
- package/src/cli/commands/knowledge/show.ts +92 -0
- package/src/cli/commands/knowledge.ts +2 -1
- package/src/cli/commands/mcp/harnesses.ts +30 -8
- package/src/cli/commands/mcp/onboarding.ts +86 -0
- package/src/cli/commands/mcp/register.ts +16 -2
- package/src/cli/commands/mcp.ts +1 -0
- package/src/cli/commands/members.ts +288 -0
- package/src/cli/commands/operate/attach.ts +3 -3
- package/src/cli/commands/operate/audit.ts +11 -7
- package/src/cli/commands/operate/auth.ts +28 -11
- package/src/cli/commands/operate/findings.ts +2 -1
- package/src/cli/commands/operate/inspect.ts +37 -19
- package/src/cli/commands/operate/migrate.ts +29 -12
- package/src/cli/commands/operate/outputs.ts +3 -3
- package/src/cli/commands/operate/pair-certificate.ts +141 -0
- package/src/cli/commands/operate/pair.ts +324 -0
- package/src/cli/commands/operate/policy.ts +73 -22
- package/src/cli/commands/operate/serve.ts +52 -4
- package/src/cli/commands/operate/status.ts +18 -10
- package/src/cli/commands/operate/tools.ts +2 -2
- package/src/cli/commands/operate.ts +2 -0
- package/src/cli/commands/owner/shared.ts +13 -2
- package/src/cli/commands/owner/skills.ts +28 -8
- package/src/cli/commands/profile/removal.ts +79 -76
- package/src/cli/commands/profile/remove.ts +16 -1
- package/src/cli/commands/profile.ts +46 -10
- package/src/cli/commands/relabel.ts +112 -0
- package/src/cli/commands/secrets.ts +34 -12
- package/src/cli/commands/set-workspace.ts +96 -0
- package/src/cli/commands/setup.ts +2 -2
- package/src/cli/commands/sync.ts +8 -8
- package/src/cli/commands/target.ts +9 -7
- package/src/cli/commands/update.ts +58 -17
- package/src/cli/config-edit.ts +75 -140
- package/src/cli/config-migrate.ts +82 -64
- package/src/cli/config-repair.ts +89 -32
- package/src/cli/config-templates.ts +198 -0
- package/src/cli/contract3-data.ts +328 -0
- package/src/cli/contract3-shape.ts +186 -0
- package/src/cli/contract3.ts +282 -0
- package/src/cli/endpoint-url.ts +1 -1
- package/src/cli/lanes.ts +25 -1
- package/src/cli/main.ts +89 -14
- package/src/cli/migrate-plan.ts +12 -6
- package/src/cli/output.ts +34 -1
- package/src/cli/publish.ts +5 -2
- package/src/cli/runtime/open.ts +63 -98
- package/src/cli/runtime/registry.ts +6 -7
- package/src/cli/runtime/stores.ts +53 -0
- package/src/cli/runtime/types.ts +106 -0
- package/src/cli/runtime/vault.ts +19 -4
- package/src/cli/runtime/workspace.ts +60 -0
- package/src/cli/runtime.ts +2 -1
- package/src/cli/selection-require.ts +44 -13
- package/src/cli/selection.ts +127 -145
- package/src/cli/usage.ts +34 -18
- package/src/cli/workspace-migrate.ts +125 -16
- package/src/connectivity/manifest/provider.ts +3 -1
- package/src/connectivity/manifest/requirements.ts +1 -1
- package/src/deployments/bind.ts +1 -1
- package/src/deployments/deploy.ts +36 -27
- package/src/deployments/gcp/bucket.ts +18 -7
- package/src/deployments/gcp/provision.ts +7 -7
- package/src/deployments/prepare.ts +72 -24
- package/src/deployments/record.ts +1 -1
- package/src/deployments/report.ts +2 -2
- package/src/deployments/serving.ts +15 -74
- package/src/deployments/target.ts +15 -15
- package/src/deployments/upload.ts +46 -22
- package/src/dispatch/deps.ts +88 -0
- package/src/dispatch/dispatch.ts +21 -62
- package/src/policy/index.ts +47 -15
- package/src/profile/connections.ts +183 -0
- package/src/profile/deployments.ts +3 -3
- package/src/profile/index.ts +30 -5
- package/src/profile/layout.ts +86 -89
- package/src/profile/load.ts +80 -47
- package/src/profile/pairing.ts +32 -0
- package/src/profile/primitives.ts +35 -1
- package/src/profile/registry.ts +6 -6
- package/src/profile/schema.ts +172 -21
- package/src/profile/targets.ts +21 -9
- package/src/profile/testing.ts +69 -2
- package/src/profile/workspace.ts +58 -3
- package/src/providers/custom/index.ts +1 -1
- package/src/providers/custom/load.ts +2 -3
- package/src/providers/identity/provider.ts +1 -1
- package/src/providers/memory/provider.ts +20 -2
- package/src/providers/setup/plan.ts +1 -1
- package/src/providers/slack/index.ts +2 -2
- package/src/registry/policy-bridge.ts +33 -11
- package/src/registry/reconcile.ts +4 -4
- package/src/server/authorization.ts +94 -0
- package/src/server/edge.ts +14 -1
- package/src/server/endpoint.ts +85 -104
- package/src/server/generation.ts +10 -1
- package/src/server/harness.ts +71 -13
- package/src/server/index.ts +31 -0
- package/src/server/mcp/build.ts +20 -1
- package/src/server/mcp/client-info.ts +54 -0
- package/src/server/mcp/guide.ts +120 -0
- package/src/server/mcp/instructions.ts +1 -1
- package/src/server/mcp/prompts.ts +7 -3
- package/src/server/mcp/resources.ts +16 -8
- package/src/server/mcp/tools.ts +9 -3
- package/src/server/mcp/visibility.ts +18 -3
- package/src/server/oauth.ts +29 -109
- package/src/server/read/credential.ts +134 -0
- package/src/server/read/deployed.ts +56 -0
- package/src/server/read/listener.ts +54 -0
- package/src/server/read/open.ts +101 -0
- package/src/server/read/routes.ts +247 -0
- package/src/server/read/state.ts +171 -0
package/src/cli/selection.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ConfigError } from '#profile';
|
|
2
2
|
import type { Flags } from './argv.ts';
|
|
3
|
-
import {
|
|
3
|
+
import { ACCEPTS } from './accepts.ts';
|
|
4
4
|
import { nearest } from './nearest.ts';
|
|
5
5
|
|
|
6
|
+
export { ACCEPTS } from './accepts.ts';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Which commands must name a profile and a target, and which flags each accepts.
|
|
8
10
|
*
|
|
@@ -10,7 +12,7 @@ import { nearest } from './nearest.ts';
|
|
|
10
12
|
* one makes the other legible.
|
|
11
13
|
*
|
|
12
14
|
* **A flag that is silently ignored is the defect.** `lanes link profile add
|
|
13
|
-
* work --
|
|
15
|
+
* work --workspace cloud` printed `ok` and dropped the flag: `main.ts` built a
|
|
14
16
|
* literal for that command and never spread the global flags into it. Nothing
|
|
15
17
|
* refused, because nothing had a list of what the command accepts. That is what
|
|
16
18
|
* `assertKnownFlags` is — and it matters more than the requirement, because
|
|
@@ -39,7 +41,7 @@ import { nearest } from './nearest.ts';
|
|
|
39
41
|
* there is no file to read. The level is gone rather than left empty, so nobody
|
|
40
42
|
* adds a sixth command to a level that cannot resolve.
|
|
41
43
|
*/
|
|
42
|
-
export type Requires = 'none' | '
|
|
44
|
+
export type Requires = 'none' | 'workspace' | 'profile+workspace';
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* The rule, per command path.
|
|
@@ -54,7 +56,7 @@ export type Requires = 'none' | 'target' | 'profile+target';
|
|
|
54
56
|
* `check`, `config show` and `policy list` take no `--target`. All three are
|
|
55
57
|
* target-independent — a YAML file, the whole of it, and a policy block that is
|
|
56
58
|
* declared once and applies everywhere. Demanding a target would be the
|
|
57
|
-
* ceremony that teaches people to type `--
|
|
59
|
+
* ceremony that teaches people to type `--workspace local` without reading it,
|
|
58
60
|
* which is how a required flag stops being a guard.
|
|
59
61
|
*
|
|
60
62
|
* `target list` takes no required `--target` either, and that is not an
|
|
@@ -85,55 +87,81 @@ export const SELECTION: Record<string, Requires> = {
|
|
|
85
87
|
// `lanes link profile` is `profile list`, and needs the same as it.
|
|
86
88
|
mcp: 'none',
|
|
87
89
|
'profile default': 'none',
|
|
90
|
+
'workspace use': 'none',
|
|
88
91
|
'target use': 'none',
|
|
89
92
|
'vault key': 'none',
|
|
90
93
|
// Listing the registry is what you run to find out what `--target` accepts, so
|
|
91
94
|
// requiring the answer as input would be circular (ADR-052).
|
|
95
|
+
workspace: 'none',
|
|
96
|
+
// The old word, kept for one minor (ADR-061).
|
|
92
97
|
target: 'none',
|
|
98
|
+
'workspace list': 'none',
|
|
93
99
|
'target list': 'none',
|
|
94
100
|
|
|
95
101
|
// A profile lives in one target's workspace, so listing or creating one names
|
|
96
102
|
// which workspace. `target show` follows the pointer, which `list` does not.
|
|
97
|
-
profile: '
|
|
98
|
-
'profile list': '
|
|
99
|
-
'profile add': '
|
|
100
|
-
'profile remove': '
|
|
101
|
-
|
|
103
|
+
profile: 'workspace',
|
|
104
|
+
'profile list': 'workspace',
|
|
105
|
+
'profile add': 'workspace',
|
|
106
|
+
'profile remove': 'workspace',
|
|
107
|
+
// Editing who may consume one profile, so it names the profile.
|
|
108
|
+
'profile members': 'profile+workspace',
|
|
109
|
+
'target show': 'workspace',
|
|
102
110
|
|
|
103
111
|
// These read one profile's file and open nothing. The target is what says
|
|
104
112
|
// which workspace holds it — required to *locate* the profile, not to open it.
|
|
105
|
-
check: 'profile+
|
|
106
|
-
config: 'profile+
|
|
107
|
-
'config show': 'profile+
|
|
108
|
-
policy: 'profile+
|
|
109
|
-
'policy list': 'profile+
|
|
110
|
-
identity: 'profile+
|
|
111
|
-
'identity list': 'profile+
|
|
112
|
-
'secrets push': 'profile+
|
|
113
|
+
check: 'profile+workspace',
|
|
114
|
+
config: 'profile+workspace',
|
|
115
|
+
'config show': 'profile+workspace',
|
|
116
|
+
policy: 'profile+workspace',
|
|
117
|
+
'policy list': 'profile+workspace',
|
|
118
|
+
identity: 'profile+workspace',
|
|
119
|
+
'identity list': 'profile+workspace',
|
|
120
|
+
'secrets push': 'profile+workspace',
|
|
113
121
|
|
|
114
|
-
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
// A connection belongs to the workspace (ADR-057), so connecting does not
|
|
123
|
+
// name a profile. `--profile` is what *also* grants it there, which is the
|
|
124
|
+
// second of the two acts and the one that is a profile's — without it the
|
|
125
|
+
// account is authorised and granted to nobody, and `connect` says how to
|
|
126
|
+
// grant it.
|
|
127
|
+
connect: 'workspace',
|
|
128
|
+
// Workspace-scoped: it answers "what has this workspace authorised", and a
|
|
129
|
+
// profile would narrow the column rather than the rows.
|
|
130
|
+
connection: 'workspace',
|
|
131
|
+
'connection list': 'workspace',
|
|
132
|
+
grant: 'profile+workspace',
|
|
133
|
+
revoke: 'profile+workspace',
|
|
134
|
+
// Both act on a connection, which belongs to the workspace (ADR-057).
|
|
135
|
+
// `disconnect` already reaches every profile that granted it and `label` is a
|
|
136
|
+
// field on the connection row, so neither had a profile to be told — naming
|
|
137
|
+
// one described a slice of a change that was never scoped to it. `--profile`
|
|
138
|
+
// still narrows what is listed back.
|
|
139
|
+
disconnect: 'workspace',
|
|
140
|
+
relabel: 'workspace',
|
|
120
141
|
// Its own row rather than an inheritance from `connect`. Both need the same
|
|
121
142
|
// two things, but the row is what makes `selectionKey` return the two-word
|
|
122
143
|
// key — and that is what keeps thirty declaration flags off
|
|
123
144
|
// `connect <provider>`, where a mistyped one would otherwise be accepted and
|
|
124
145
|
// ignored, which is the defect this whole file exists for.
|
|
125
|
-
'connect custom': '
|
|
126
|
-
setup: 'profile+
|
|
127
|
-
token: 'profile+
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
146
|
+
'connect custom': 'workspace',
|
|
147
|
+
setup: 'profile+workspace',
|
|
148
|
+
token: 'profile+workspace',
|
|
149
|
+
// One chain per workspace since contract 3, so the workspace is the subject
|
|
150
|
+
// and `--profile` filters the rows rather than choosing which log to read.
|
|
151
|
+
audit: 'workspace',
|
|
152
|
+
// One credential store per workspace since contract 3, so every profile
|
|
153
|
+
// opened the same one.
|
|
154
|
+
secrets: 'workspace',
|
|
155
|
+
plan: 'profile+workspace',
|
|
156
|
+
doctor: 'profile+workspace',
|
|
157
|
+
// Whether an account can still sign in is a fact about the account. Scoped to
|
|
158
|
+
// a profile's grants it could not check one that had just been connected,
|
|
159
|
+
// which is when you most want to.
|
|
160
|
+
auth: 'workspace',
|
|
133
161
|
// Target-scoped: see the note above. `--profile` narrows each to one profile.
|
|
134
|
-
status: '
|
|
135
|
-
outputs: 'profile+
|
|
136
|
-
tools: 'profile+
|
|
162
|
+
status: 'workspace',
|
|
163
|
+
outputs: 'profile+workspace',
|
|
164
|
+
tools: 'profile+workspace',
|
|
137
165
|
// It resolves nothing and opens nothing — it hands macOS a URL (ADR-053).
|
|
138
166
|
// `target list` is the precedent for a `'none'` command that still takes a
|
|
139
167
|
// flag of its own. Both spellings need a row: `selection.test.ts` reads
|
|
@@ -141,38 +169,48 @@ export const SELECTION: Record<string, Requires> = {
|
|
|
141
169
|
// the `profile+target` default.
|
|
142
170
|
dashboard: 'none',
|
|
143
171
|
desktop: 'none',
|
|
144
|
-
attach: 'profile+
|
|
145
|
-
|
|
146
|
-
|
|
172
|
+
attach: 'profile+workspace',
|
|
173
|
+
// One endpoint serves every profile in the workspace (ADR-009), so naming one
|
|
174
|
+
// described a slice of what it does. `--profile` picks the primary, whose
|
|
175
|
+
// token opens it, and `--only` is what narrows what is served.
|
|
176
|
+
start: 'workspace',
|
|
177
|
+
deploy: 'workspace',
|
|
147
178
|
// Both spellings: `sync` alone is `sync targets`, which is the only thing
|
|
148
179
|
// there is to sync, and naming it leaves room for the next one.
|
|
149
|
-
sync: '
|
|
150
|
-
'sync targets': '
|
|
151
|
-
'
|
|
152
|
-
'policy
|
|
180
|
+
sync: 'workspace',
|
|
181
|
+
'sync targets': 'workspace',
|
|
182
|
+
'sync workspaces': 'workspace',
|
|
183
|
+
'policy allow': 'profile+workspace',
|
|
184
|
+
'policy deny': 'profile+workspace',
|
|
153
185
|
// Both, unlike `identity list`, and for the same reason the policy edits are:
|
|
154
186
|
// each publishes the edit, which opens the target's credential store and
|
|
155
187
|
// reaches that target's endpoint.
|
|
156
|
-
'identity add': 'profile+
|
|
157
|
-
'identity remove': 'profile+
|
|
158
|
-
'
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
'
|
|
165
|
-
'
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
188
|
+
'identity add': 'profile+workspace',
|
|
189
|
+
'identity remove': 'profile+workspace',
|
|
190
|
+
'mcp install-instructions': 'none',
|
|
191
|
+
// What it pairs is the workspace: the surface it opens lists every connection
|
|
192
|
+
// and profile there, and the credential it mints reads all of them. Asking
|
|
193
|
+
// which profile was a question with no answer. `--profile` still narrows, and
|
|
194
|
+
// is how a port is chosen when profiles disagree about one.
|
|
195
|
+
pair: 'workspace',
|
|
196
|
+
'token show': 'profile+workspace',
|
|
197
|
+
'token rotate': 'profile+workspace',
|
|
198
|
+
'audit tail': 'workspace',
|
|
199
|
+
'audit verify': 'workspace',
|
|
200
|
+
'secrets set': 'workspace',
|
|
201
|
+
'secrets list': 'workspace',
|
|
202
|
+
'mcp add': 'profile+workspace',
|
|
203
|
+
'mcp stdio': 'profile+workspace',
|
|
204
|
+
memory: 'profile+workspace',
|
|
205
|
+
tasks: 'profile+workspace',
|
|
206
|
+
assets: 'profile+workspace',
|
|
207
|
+
skills: 'profile+workspace',
|
|
208
|
+
vault: 'profile+workspace',
|
|
209
|
+
entities: 'profile+workspace',
|
|
172
210
|
// Both halves open the target's adapters — `show` counts what is in the
|
|
173
211
|
// stores, and `use` migrates between them — and both edit the profile's
|
|
174
212
|
// config. Neither can be answered without being told which.
|
|
175
|
-
knowledge: 'profile+
|
|
213
|
+
knowledge: 'profile+workspace',
|
|
176
214
|
};
|
|
177
215
|
|
|
178
216
|
/**
|
|
@@ -186,7 +224,9 @@ export const SELECTION: Record<string, Requires> = {
|
|
|
186
224
|
* asserts this stays true.
|
|
187
225
|
*/
|
|
188
226
|
const SUBCOMMANDS: Record<string, readonly string[]> = {
|
|
189
|
-
profile: ['add', 'list', 'default', 'remove'],
|
|
227
|
+
profile: ['add', 'list', 'default', 'remove', 'members'],
|
|
228
|
+
connection: ['list'],
|
|
229
|
+
workspace: ['list', 'use', 'show'],
|
|
190
230
|
target: ['list', 'use', 'show'],
|
|
191
231
|
policy: ['list', 'allow', 'deny'],
|
|
192
232
|
identity: ['add', 'list', 'remove'],
|
|
@@ -205,7 +245,7 @@ const SUBCOMMANDS: Record<string, readonly string[]> = {
|
|
|
205
245
|
mcp: ['skill', 'add', 'stdio', 'list'],
|
|
206
246
|
secrets: ['push', 'set', 'list'],
|
|
207
247
|
knowledge: ['show', 'use'],
|
|
208
|
-
sync: ['targets'],
|
|
248
|
+
sync: ['targets', 'workspaces'],
|
|
209
249
|
};
|
|
210
250
|
|
|
211
251
|
/**
|
|
@@ -235,99 +275,41 @@ export function selectionKey(first: string, second: string | undefined): string
|
|
|
235
275
|
|
|
236
276
|
/** Whether this command needs a profile, a target, both, or neither. */
|
|
237
277
|
export function requirementFor(first: string, second: string | undefined): Requires {
|
|
238
|
-
return SELECTION[selectionKey(first, second)] ?? 'profile+
|
|
278
|
+
return SELECTION[selectionKey(first, second)] ?? 'profile+workspace';
|
|
239
279
|
}
|
|
240
280
|
|
|
241
|
-
const UNIVERSAL = ['help', 'json', 'quiet'];
|
|
242
|
-
|
|
243
281
|
/**
|
|
244
|
-
*
|
|
282
|
+
* The commands that refuse `default_workspace` and make you type the name.
|
|
283
|
+
*
|
|
284
|
+
* ADR-037 removed every implicit selection, on reasoning worth keeping: a
|
|
285
|
+
* persisted context is the standard way an operator runs a destructive command
|
|
286
|
+
* against the wrong thing. ADR-061 gives the default back for the forty
|
|
287
|
+
* commands a day that only read, and keeps the refusal exactly where that
|
|
288
|
+
* argument bites — anything that publishes or destroys.
|
|
245
289
|
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
290
|
+
* `connect` is deliberately absent. It creates rather than destroys, it is the
|
|
291
|
+
* command someone runs while learning the tool, and it prints the workspace it
|
|
292
|
+
* wrote to. Requiring a flag there is the ceremony ADR-043 identified as the way
|
|
293
|
+
* a required flag stops being a guard.
|
|
248
294
|
*/
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
'
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
// provider its address without a terminal to ask at.
|
|
262
|
-
'set',
|
|
263
|
-
'label',
|
|
264
|
-
'replace',
|
|
265
|
-
'non-interactive',
|
|
266
|
-
'accept-broad-scopes',
|
|
267
|
-
'own-client',
|
|
268
|
-
'auth',
|
|
269
|
-
],
|
|
270
|
-
setup: ['id'],
|
|
271
|
-
'profile add': ['target', 'non-interactive'],
|
|
272
|
-
// `--target` decommissions one target's stores and leaves the profile file in
|
|
273
|
-
// place (`removal.ts`). It is documented in `usage.ts` and read by
|
|
274
|
-
// `removalPlan`, and was refused here — the flag existed everywhere except in
|
|
275
|
-
// the list that decides whether it may be typed.
|
|
276
|
-
'profile remove': ['dry-run', 'yes', 'target'],
|
|
277
|
-
disconnect: ['yes', 'keep-credential'],
|
|
278
|
-
// The one repair `doctor` can apply rather than only name. Narrow on purpose:
|
|
279
|
-
// it undoes a provider rename this project shipped, and every other finding
|
|
280
|
-
// there is something only the operator can decide.
|
|
281
|
-
doctor: ['fix'],
|
|
282
|
-
// A filter, not a second subject: it narrows the answer to one connection so
|
|
283
|
-
// a caller can re-ask about the row it just repaired. Same shape as `attach`.
|
|
284
|
-
auth: ['connection'],
|
|
285
|
-
relabel: [],
|
|
286
|
-
'target list': ['urls', 'target'],
|
|
287
|
-
'target show': ['target'],
|
|
288
|
-
'token show': ['show', 'raw'],
|
|
289
|
-
'token rotate': ['show', 'raw', 'yes'],
|
|
290
|
-
'audit tail': ['limit', 'denied-only', 'format'],
|
|
291
|
-
'audit verify': ['limit', 'format'],
|
|
292
|
-
attach: ['connection'],
|
|
293
|
-
outputs: ['show'],
|
|
294
|
-
start: ['port', 'only'],
|
|
295
|
-
'mcp stdio': ['only'],
|
|
296
|
-
'mcp add': ['name', 'scope', 'token-env', 'dry-run', 'force', 'no-skill'],
|
|
297
|
-
'mcp skill': ['print', 'force'],
|
|
298
|
-
'mcp list': ['name', 'scope'],
|
|
299
|
-
// `--yes` because it installs the app when nothing answers the scheme, and
|
|
300
|
-
// that is the one prompt in this CLI that puts an application on the machine.
|
|
301
|
-
dashboard: ['print', 'yes'],
|
|
302
|
-
desktop: ['print', 'yes'],
|
|
303
|
-
skill: ['print', 'force'],
|
|
304
|
-
deploy: ['dry-run', 'iam', 'access', 'service-account', 'tag', 'yes', 'non-interactive'],
|
|
305
|
-
'secrets push': ['from', 'to', 'overwrite', 'dry-run'],
|
|
306
|
-
sync: ['dry-run', 'from', 'discover', 'prefer'],
|
|
307
|
-
'sync targets': ['dry-run', 'from', 'discover', 'prefer'],
|
|
308
|
-
update: ['check'],
|
|
309
|
-
'identity add': ['note'],
|
|
310
|
-
memory: ['connection', 'title', 'description', 'file', 'tag'],
|
|
311
|
-
// `--yes` on both, because both have a delete that asks first.
|
|
312
|
-
tasks: ['connection', 'title', 'status', 'due', 'tag', 'yes'],
|
|
313
|
-
assets: ['connection', 'name', 'content-type', 'yes'],
|
|
314
|
-
skills: ['connection', 'title', 'description', 'file'],
|
|
315
|
-
vault: ['connection'],
|
|
316
|
-
// `alias`, `attr` and `related` are repeatable — see `ownerFlags`. `name`
|
|
317
|
-
// overrides the id derived from the positional name, which is how you get
|
|
318
|
-
// `acme-bv` rather than `acme-b-v`.
|
|
319
|
-
entities: ['connection', 'type', 'name', 'alias', 'attr', 'related', 'tag', 'yes'],
|
|
320
|
-
// `no-migrate` is listed beside `migrate` because they are three states
|
|
321
|
-
// rather than two: neither one asks, and a run with no terminal has to be
|
|
322
|
-
// able to say which it meant (ADR-041).
|
|
323
|
-
knowledge: ['repo', 'branch', 'path', 'migrate', 'no-migrate', 'keep', 'allow-public', 'replace', 'yes'],
|
|
324
|
-
};
|
|
295
|
+
export const EXPLICIT_WORKSPACE = new Set([
|
|
296
|
+
'deploy',
|
|
297
|
+
'sync',
|
|
298
|
+
'sync targets',
|
|
299
|
+
'sync workspaces',
|
|
300
|
+
'secrets push',
|
|
301
|
+
'profile remove',
|
|
302
|
+
'disconnect',
|
|
303
|
+
'token rotate',
|
|
304
|
+
]);
|
|
305
|
+
|
|
306
|
+
const UNIVERSAL = ['help', 'json', 'quiet'];
|
|
325
307
|
|
|
326
308
|
/**
|
|
327
309
|
* Refuse a flag this command does not read, and guess what was meant.
|
|
328
310
|
*
|
|
329
311
|
* This is the fix for the reported bug rather than a nicety. `profile add
|
|
330
|
-
* --
|
|
312
|
+
* --workspace cloud` was accepted and dropped, and nothing could refuse it because
|
|
331
313
|
* `parseArgv` returns every `--anything` it sees and no command ever inspected
|
|
332
314
|
* the leftovers. A typo was swallowed the same way on every command in the CLI.
|
|
333
315
|
*/
|
|
@@ -345,7 +327,7 @@ export function assertKnownFlags(first: string, second: string | undefined, flag
|
|
|
345
327
|
if (dispatchWillRefuse(first, second)) return;
|
|
346
328
|
|
|
347
329
|
const key = selectionKey(first, second);
|
|
348
|
-
const needs = SELECTION[key] ?? 'profile+
|
|
330
|
+
const needs = SELECTION[key] ?? 'profile+workspace';
|
|
349
331
|
|
|
350
332
|
const allowed = new Set<string>([
|
|
351
333
|
...UNIVERSAL,
|
|
@@ -353,7 +335,7 @@ export function assertKnownFlags(first: string, second: string | undefined, flag
|
|
|
353
335
|
// `target` accepts both: the target is what it acts on, and `--profile`
|
|
354
336
|
// narrows it to one of the profiles behind it.
|
|
355
337
|
...(needs !== 'none' && !POSITIONAL_PROFILE.has(key) ? ['profile'] : []),
|
|
356
|
-
...(needs === '
|
|
338
|
+
...(needs === 'workspace' || needs === 'profile+workspace' ? ['workspace'] : []),
|
|
357
339
|
]);
|
|
358
340
|
|
|
359
341
|
const named = [first, second].filter(Boolean).join(' ');
|
package/src/cli/usage.ts
CHANGED
|
@@ -21,7 +21,8 @@ export const USAGE = `${style.bold(PROGRAM)} — a self-hostable MCP gateway for
|
|
|
21
21
|
${style.bold('Everyday')}
|
|
22
22
|
${PROGRAM} setup plan [--json] what each provider needs, and which are connected
|
|
23
23
|
${PROGRAM} setup plan <provider> the console steps, the values, and the command
|
|
24
|
-
${PROGRAM} connect <provider>
|
|
24
|
+
${PROGRAM} connect <provider> authorise an account into this workspace
|
|
25
|
+
(once per account, not once per profile)
|
|
25
26
|
${PROGRAM} connect <provider>.<id> re-authorise one existing account
|
|
26
27
|
${PROGRAM} connect <...> --replace ask for the stored password or key again
|
|
27
28
|
${PROGRAM} connect <...> --auth <method> pick how, where there is a choice
|
|
@@ -35,6 +36,9 @@ ${style.bold('Everyday')}
|
|
|
35
36
|
asked for; the manifest it writes is yours to edit
|
|
36
37
|
answer nothing from a terminal: take every value
|
|
37
38
|
from the credential store, or say what is missing
|
|
39
|
+
${PROGRAM} connection list [--json] every account in this workspace, and who grants it
|
|
40
|
+
${PROGRAM} grant add <provider>.<id> let a profile reach one, with nothing allowed yet
|
|
41
|
+
${PROGRAM} grant remove <provider>.<id>
|
|
38
42
|
${PROGRAM} start [--only] reconcile and serve every profile on one endpoint
|
|
39
43
|
${PROGRAM} outputs [--show] [--json] the endpoint an agent needs
|
|
40
44
|
${PROGRAM} desktop [--print] [--yes] open the Lanes app on its Lanes Link page,
|
|
@@ -45,24 +49,27 @@ ${style.bold('Everyday')}
|
|
|
45
49
|
${PROGRAM} mcp list where it is registered, and whether the skill is current
|
|
46
50
|
${PROGRAM} mcp stdio serve on stdin/stdout, for a client that spawns it
|
|
47
51
|
${PROGRAM} mcp skill [--print] the bundled skill — its path, or the document itself
|
|
52
|
+
${PROGRAM} mcp install-instructions [--client claude|chatgpt|codex|cursor]
|
|
53
|
+
a block to paste where a client keeps its own
|
|
54
|
+
standing instructions, so it knows to look here
|
|
55
|
+
${PROGRAM} pair [--print] [--rotate] let the Lanes dashboard read this machine
|
|
48
56
|
${PROGRAM} status [--json] connections, reachable capabilities, endpoint
|
|
49
57
|
|
|
50
58
|
${style.bold('Profiles')}
|
|
51
|
-
${PROGRAM} profile add <name> --
|
|
59
|
+
${PROGRAM} profile add <name> --workspace <name> [--workspace <name>] [--json]
|
|
52
60
|
a target per place it runs; local is derived, the
|
|
53
61
|
rest are copied from a sibling profile
|
|
54
62
|
${PROGRAM} profile list [--json]
|
|
55
|
-
${PROGRAM} profile remove <name> [--
|
|
63
|
+
${PROGRAM} profile remove <name> [--workspace <name>] [--dry-run] [--yes] [--json]
|
|
56
64
|
the profile, its credentials, and its data
|
|
57
65
|
|
|
58
|
-
${style.bold('
|
|
59
|
-
${PROGRAM}
|
|
60
|
-
${PROGRAM}
|
|
61
|
-
${PROGRAM} sync
|
|
66
|
+
${style.bold('Workspaces')}
|
|
67
|
+
${PROGRAM} workspace list [--urls] every workspace this one knows
|
|
68
|
+
${PROGRAM} workspace show <name> one workspace's adapters, and its address
|
|
69
|
+
${PROGRAM} sync workspaces --workspace <name> [--from gs://bucket] [--discover]
|
|
62
70
|
[--prefer local|remote] [--dry-run]
|
|
63
71
|
reconcile this workspace with the copy the
|
|
64
|
-
deployment reads; recovers a
|
|
65
|
-
has lost
|
|
72
|
+
deployment reads; recovers one a profile has lost
|
|
66
73
|
|
|
67
74
|
${style.bold('Who you are')}
|
|
68
75
|
${PROGRAM} identity add <kind> <value> [--note text] [--json]
|
|
@@ -72,10 +79,15 @@ ${style.bold('Who you are')}
|
|
|
72
79
|
|
|
73
80
|
${style.bold('Permissions')}
|
|
74
81
|
${PROGRAM} policy list
|
|
75
|
-
${PROGRAM} policy allow <capability>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
${PROGRAM}
|
|
82
|
+
${PROGRAM} policy allow <capability> --connection <provider>.<id>
|
|
83
|
+
e.g. gmail.* or gmail.send_message. A rule lands
|
|
84
|
+
in one grant, so two accounts can differ
|
|
85
|
+
${PROGRAM} policy deny <capability> --connection <provider>.<id>
|
|
86
|
+
${PROGRAM} profile members list who may consume this profile, and who could
|
|
87
|
+
${PROGRAM} profile members add <subject>|--me [--role owner|member]
|
|
88
|
+
${PROGRAM} profile members remove <subject>
|
|
89
|
+
${PROGRAM} token show [--show|--raw] CI only: --raw prints only the token, for $(…)
|
|
90
|
+
${PROGRAM} token rotate [--show] also ends every session a member holds
|
|
79
91
|
|
|
80
92
|
${style.bold('Your own context')}
|
|
81
93
|
${PROGRAM} memory list [--tag t] what you have stored
|
|
@@ -126,10 +138,10 @@ ${style.bold('Your own context')}
|
|
|
126
138
|
${PROGRAM} vault key generate a fresh LANES_LINK_VAULT_KEY, printed once
|
|
127
139
|
|
|
128
140
|
${style.bold('Deploying')}
|
|
129
|
-
${PROGRAM} deploy --
|
|
141
|
+
${PROGRAM} deploy --workspace <name> [--dry-run]
|
|
130
142
|
set up, build, and roll one revision serving
|
|
131
143
|
every profile that declares the target
|
|
132
|
-
${PROGRAM} deploy --
|
|
144
|
+
${PROGRAM} deploy --workspace <name> --profile a --profile b
|
|
133
145
|
only these; the first owns the endpoint token
|
|
134
146
|
${PROGRAM} deploy --non-interactive take the stored answers, never prompt
|
|
135
147
|
${PROGRAM} deploy --access iam|public who gets past the platform's own door
|
|
@@ -158,9 +170,13 @@ ${style.bold('Attachments')}
|
|
|
158
170
|
|
|
159
171
|
${style.bold('Naming what a command acts on')}
|
|
160
172
|
--profile <name> required by every command that reads or writes a profile
|
|
161
|
-
--
|
|
162
|
-
|
|
163
|
-
command that
|
|
173
|
+
--workspace <name> required by every command that opens a workspace's
|
|
174
|
+
stores. "lanes set-workspace <name>" writes a default;
|
|
175
|
+
every command that uses it prints the name it resolved,
|
|
176
|
+
and deploy, sync, secrets push, profile remove,
|
|
177
|
+
disconnect and token rotate refuse it and want the flag.
|
|
178
|
+
--target <name> the old spelling of --workspace. Accepted for one
|
|
179
|
+
minor, and it warns.
|
|
164
180
|
|
|
165
181
|
${style.bold('Other flags')}
|
|
166
182
|
--connection <id> which memory/tasks/assets/skills/vault/entities
|