@hasna/skills 0.4.0 → 0.5.1
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 +220 -5
- package/bin/index.js +7747 -5645
- package/bin/mcp.js +1493 -431
- package/bin/migrate.js +148 -40
- package/bin/server.js +53 -83
- package/bin/worker.js +41 -73
- package/dist/admin-contract.d.ts +37 -19
- package/dist/admin-contract.js +1 -1
- package/dist/cli/cli.test-utils.d.ts +10 -8
- package/dist/cli/commands/customer-profile.d.ts +2 -0
- package/dist/cli/commands/customer-verification.d.ts +5 -0
- package/dist/cli/commands/tool-primitives.d.ts +1 -1
- package/dist/cli/commands/workspace-member-mutations.d.ts +2 -0
- package/dist/cli/commands/workspace-members.d.ts +2 -0
- package/dist/cli/commands/workspace-selection.d.ts +11 -0
- package/dist/cli/env-assignment.d.ts +9 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +841 -167
- package/dist/lib/agent-sync.d.ts +13 -8
- package/dist/lib/api-url.d.ts +4 -3
- package/dist/lib/app-home.d.ts +0 -1
- package/dist/lib/client-types.d.ts +75 -0
- package/dist/lib/credential-state.d.ts +12 -0
- package/dist/lib/fleet-credentials.d.ts +41 -15
- package/dist/lib/home-adoption.d.ts +2 -0
- package/dist/lib/home-census.d.ts +3 -1
- package/dist/lib/local-opt-in.d.ts +24 -0
- package/dist/lib/portable-skills-files.d.ts +6 -2
- package/dist/lib/read-access.d.ts +83 -0
- package/dist/lib/remote-auth.d.ts +23 -3
- package/dist/lib/remote-client.d.ts +45 -5
- package/dist/lib/remote-profile.d.ts +26 -0
- package/dist/lib/remote-registry.d.ts +7 -3
- package/dist/lib/remote-workspace-selection.d.ts +58 -0
- package/dist/lib/remote-workspace.d.ts +76 -0
- package/dist/lib/skillinfo.d.ts +1 -1
- package/dist/lib/workspace-profile.d.ts +49 -0
- package/dist/mcp/helpers.d.ts +22 -0
- package/dist/mcp/index.d.ts +16 -0
- package/dist/sdk/governance-store.d.ts +1 -0
- package/dist/sdk/index.d.ts +8 -2
- package/dist/sdk/index.js +1312 -297
- package/dist/sdk/outputs.d.ts +0 -11
- package/dist/sdk/runs.d.ts +1 -1
- package/dist/storage.js +6 -40
- package/docs/skill-standard.md +30 -2
- package/package.json +6 -4
- package/dist/lib/instance-credentials-race.fixture.d.ts +0 -1
package/README.md
CHANGED
|
@@ -124,7 +124,7 @@ The unprefixed `SKILLS_API_KEY` and `SKILLS_API_URL` spellings are still accepte
|
|
|
124
124
|
as silent aliases one rung below the canonical names, for one release. Use the
|
|
125
125
|
`HASNA_`-prefixed names. `SKILL_API_KEY` (singular) is no longer read at all.
|
|
126
126
|
|
|
127
|
-
**
|
|
127
|
+
**Fail closed, and the local run is a deliberate choice:**
|
|
128
128
|
|
|
129
129
|
- a credential resolves → **hosted**, against the configured URL or the gateway.
|
|
130
130
|
A credential that resolves but cannot produce a usable key — a deliberate
|
|
@@ -133,14 +133,39 @@ as silent aliases one rung below the canonical names, for one release. Use the
|
|
|
133
133
|
- no credential but a URL is configured → **loud failure**, exit non-zero. There
|
|
134
134
|
is no local fallback: answering from the bundled corpus while authentication is
|
|
135
135
|
unconfigured is a false green;
|
|
136
|
-
- neither
|
|
137
|
-
|
|
136
|
+
- neither a credential nor a URL, and no opt-in → **loud failure**, exit
|
|
137
|
+
non-zero. Running on this machine is no longer the silence that follows a
|
|
138
|
+
missing credential: an unconfigured install fails closed, opening no local
|
|
139
|
+
database and emitting no local-fallback event, and the error names the way
|
|
140
|
+
out and where the credential should live. This holds on every data surface:
|
|
141
|
+
`list`, `search`, `categories`, `tags`, `info`, `show`, `docs`, `requires`
|
|
142
|
+
and the bare `skills` listing all exit 1; `skills-mcp` exits 1 at startup
|
|
143
|
+
before answering `initialize` or binding a port, and each MCP data tool
|
|
144
|
+
answers `AUTH_REQUIRED` on its own;
|
|
145
|
+
- the explicit local opt-in → **local**. Skills ships its corpus, so running on
|
|
146
|
+
this machine is a real mode — but it must be asked for:
|
|
147
|
+
`HASNA_SKILLS_LOCAL=1` (alias `SKILLS_LOCAL=1`). It prints one line saying
|
|
148
|
+
"local mode" on stderr. A configured environment always outranks the opt-in:
|
|
149
|
+
with an authority or credential in the environment, `HASNA_SKILLS_LOCAL` is
|
|
150
|
+
ignored and the run goes (or fails) hosted.
|
|
138
151
|
|
|
139
152
|
The retired locations are not read: `auth.json` (in either the app directory or
|
|
140
153
|
the legacy `~/.skills/`), the old fleet-env and per-machine cloud env folders
|
|
141
154
|
under `~/.hasna`, and the XDG config directory. `~/.hasna` is a closed namespace
|
|
142
155
|
of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
143
156
|
|
|
157
|
+
### Routing environment variables
|
|
158
|
+
|
|
159
|
+
| Variable | Meaning |
|
|
160
|
+
|---|---|
|
|
161
|
+
| `HASNA_SKILLS_API_KEY` | The API key (tier 5 of the ladder). The silent alias `SKILLS_API_KEY` is accepted for one release. |
|
|
162
|
+
| `HASNA_SKILLS_API_URL` | The Skills API origin (HTTPS, or loopback HTTP). The silent alias `SKILLS_API_URL` is accepted for one release. |
|
|
163
|
+
| `HASNA_SKILLS_LOCAL` | Explicit unhosted opt-in: run on this machine against the bundled corpus when no authority is configured. Any non-blank value (`1`). Alias `SKILLS_LOCAL`. Ignored whenever an authority or credential variable IS set. |
|
|
164
|
+
| `HASNA_SKILLS_API_KEY_OVERRIDE` | Deliberate tier-2 key that outranks every store. |
|
|
165
|
+
| `HASNA_SKILLS_API_KEY_REF` | Deliberate tier-2 vault-item pointer (resolved through `@hasna/secrets`). |
|
|
166
|
+
| `HASNA_PROFILE` | Selects an isolated `credentials-<profile>` file (tier 1). |
|
|
167
|
+
| `HASNA_STATION` | The Keychain account for tier 3; falls back to `hostname -s`, then `$USER`. |
|
|
168
|
+
|
|
144
169
|
## CLI Commands
|
|
145
170
|
|
|
146
171
|
| Command | Alias | Description |
|
|
@@ -151,7 +176,7 @@ of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
|
151
176
|
| `skills unpin <name>` | | Remove a project pin |
|
|
152
177
|
| `skills pins list` | | List pinned skills |
|
|
153
178
|
| `skills setup --api-url <url>` | | Point the CLI at a Skills API origin for remote runs |
|
|
154
|
-
| `skills setup` | | Show whether an API origin is configured; with none,
|
|
179
|
+
| `skills setup` | | Show whether an API origin is configured; with none, running on this machine requires `HASNA_SKILLS_LOCAL=1` |
|
|
155
180
|
| `skills setup agents` | | Register the Skills MCP server with all supported agents |
|
|
156
181
|
| `skills list` | `ls` | List available skills (filter with `-c`, `--pinned`, `-t`, `--brief`) |
|
|
157
182
|
| `skills search <query>` | `s` | Search by name, description, or tags |
|
|
@@ -168,6 +193,7 @@ of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
|
168
193
|
| `skills categories` | | List all categories with skill counts |
|
|
169
194
|
| `skills tags` | | List all unique tags with occurrence counts |
|
|
170
195
|
| `skills doctor` | | Check env vars, system deps, and pinned skill health |
|
|
196
|
+
| `skills env-check [name]` | `check-env` | Show required environment variables; `--set KEY=VALUE` updates the project's `.env` |
|
|
171
197
|
| `skills test [name]` | | Test skill readiness (env, system, npm deps) |
|
|
172
198
|
| `skills outdated` | | Compare pinned vs registry versions |
|
|
173
199
|
| `skills auth login --api-key <key>` | | Verify and store a Skills API key |
|
|
@@ -186,6 +212,7 @@ of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
|
186
212
|
| `skills create <name>` | | Scaffold a new custom skill directory |
|
|
187
213
|
| `skills sync --to claude` | | Disabled by design; use `skills mcp --register <agent|all>` |
|
|
188
214
|
| `skills sync --from claude` | | Disabled by design; agent skill folders are not used |
|
|
215
|
+
| `skills sync [names...] --check --for <agent> --source <path>` | `render` | Read-only drift census for the selected corpus, skills and agent; explicit source overrides `SKILLS_SOURCE`, then the installed cache. Unknown selections or drift exit nonzero. Without selectors, check all existing agent homes. |
|
|
189
216
|
| `skills sync --station <id>` | | Per-station snapshot mode: snapshot the installed skill homes into `resources/<station>/skills` with a v3 sync-manifest (dry-run by default; `--populate` writes) |
|
|
190
217
|
| `skills hydrate --station <id>` | | Restore the canonical corpus cache from a reviewed per-station snapshot (dry-run by default; `--apply` writes) |
|
|
191
218
|
| `skills validate <name>` | | Check a skill's directory structure |
|
|
@@ -198,6 +225,30 @@ of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
|
|
|
198
225
|
| `skills self-update` | | Update this package to the latest version |
|
|
199
226
|
| `skills completion <shell>` | | Generate shell completions (bash, zsh, fish) |
|
|
200
227
|
|
|
228
|
+
`self-update` asks the same Bun executable for its global bin directory after a
|
|
229
|
+
successful installation. It reports success only when the `skills` command on
|
|
230
|
+
your PATH resolves to that installed command and exits successfully with one
|
|
231
|
+
semantic version. If discovery or verification fails, it exits nonzero and
|
|
232
|
+
explains that installation may already have completed. It does not automatically
|
|
233
|
+
reinstall or change your PATH.
|
|
234
|
+
|
|
235
|
+
### Local environment assignments
|
|
236
|
+
|
|
237
|
+
`skills env-check --set 'KEY=value'` writes one literal value to the current
|
|
238
|
+
project's `.env`. Keys must match `[A-Za-z_][A-Za-z0-9_]*`. Empty values and `=`
|
|
239
|
+
within a value are supported; output confirms the key and path without printing
|
|
240
|
+
the value. Quote the shell argument when it contains shell metacharacters.
|
|
241
|
+
|
|
242
|
+
The writer preserves unrelated lines, comments, line endings and existing file
|
|
243
|
+
permissions. New files use mode `0600`. Symlinks and special files are rejected.
|
|
244
|
+
Values containing control characters, newlines, all three quote delimiters, an
|
|
245
|
+
odd trailing backslash, a backslash immediately before a final dollar, or a
|
|
246
|
+
backslash together with both a single quote and a backtick are rejected because
|
|
247
|
+
literal Bun dotenv serialization is not supported
|
|
248
|
+
for those cases. Multiline or ambiguous existing assignments also
|
|
249
|
+
require manual editing; refusal leaves the file unchanged. Literal round trips
|
|
250
|
+
are tested with Bun 1.3.14 and 1.4.0.
|
|
251
|
+
|
|
201
252
|
### Common Options
|
|
202
253
|
|
|
203
254
|
- `--json` — Output as JSON (pipeable)
|
|
@@ -255,6 +306,19 @@ Stable command shapes:
|
|
|
255
306
|
served by the API and never ships in this package.
|
|
256
307
|
- Config and schedules: `config * --json` and `schedule * --json` return
|
|
257
308
|
machine-readable status objects.
|
|
309
|
+
`schedule run` exits 1 if any item fails, in human and JSON output. JSON
|
|
310
|
+
`results[].attempted` identifies items handed to the local executor; `ran`
|
|
311
|
+
counts those attempts, including failures. Missing skills, routing refusals,
|
|
312
|
+
and unsupported hosted scheduling leave that occurrence due and its history
|
|
313
|
+
unchanged. Local attempts record success/error and advance the schedule.
|
|
314
|
+
If history cannot be saved, the item reports `executionStatus` and
|
|
315
|
+
`historyError`; inspect its effects before retrying. Other due items still run.
|
|
316
|
+
No-due and `--dry-run` remain successful without consuming occurrences.
|
|
317
|
+
With `schedule run --json`, child stdout and stderr stream to stderr while
|
|
318
|
+
stdout contains only the command's JSON result. Human-mode child output is
|
|
319
|
+
unchanged. Programmatic `runSkill` callers can select `stdio: "stderr"` to
|
|
320
|
+
stream both child output channels to stderr without buffering; the existing
|
|
321
|
+
default/inherit and pipe modes retain their behavior.
|
|
258
322
|
- Storage: `storage status --json` returns local `.skills` paths and optional
|
|
259
323
|
repo-native remote readiness; `storage sync-plan --json` returns a no-network
|
|
260
324
|
snapshot plan.
|
|
@@ -314,6 +378,16 @@ skills show my-skill
|
|
|
314
378
|
skills port ./existing-skill
|
|
315
379
|
```
|
|
316
380
|
|
|
381
|
+
New and imported local skill names use hyphens: `MyHTTPTool` becomes
|
|
382
|
+
`my-http-tool`, and `my_tool.v2` becomes `my-tool-v2`. Existing installed names
|
|
383
|
+
and declared command names remain readable without renaming. Already joined
|
|
384
|
+
lowercase words are not split automatically; supply `--name my-skill` when importing.
|
|
385
|
+
An import updates name declarations in its copied files; original source files stay unchanged.
|
|
386
|
+
|
|
387
|
+
Single-folder `port` / `add` reports validation after importing. If validation
|
|
388
|
+
fails, both human and JSON output exit with status 1; the imported folder remains
|
|
389
|
+
available for correction. Check `valid` and `issues` in JSON before using it.
|
|
390
|
+
|
|
317
391
|
The scaffold includes `SKILL.md`, `skill.json`, `AGENTS.md`, `package.json`,
|
|
318
392
|
`tsconfig.json`, and `src/index.ts`. `AGENTS.md` is written for coding agents:
|
|
319
393
|
after `skills new my-skill`, an agent can open that file, implement the skill,
|
|
@@ -600,7 +674,7 @@ skills/ # Public skill contracts and local OSS skills
|
|
|
600
674
|
|---|---|---|
|
|
601
675
|
| Catalog skills | 86 | `SKILLS.length` (`src/lib/registry-data/`) |
|
|
602
676
|
| Categories | 17 | `CATEGORIES` (`src/lib/registry-types.ts`) |
|
|
603
|
-
| MCP tools |
|
|
677
|
+
| MCP tools | 61 | `tools/list` against a live `buildServer()` |
|
|
604
678
|
|
|
605
679
|
Every number in this table is re-derived from the source tree on each test run by
|
|
606
680
|
`src/lib/readme-derived-counts.test.ts`, so a drifted figure fails a test rather
|
|
@@ -718,3 +792,144 @@ hand.
|
|
|
718
792
|
## License
|
|
719
793
|
|
|
720
794
|
Apache-2.0 — see [LICENSE](LICENSE)
|
|
795
|
+
|
|
796
|
+
### Account and workspace names on a compatible server
|
|
797
|
+
|
|
798
|
+
`skills account update --display-name "Ana" --email you@example.com` and
|
|
799
|
+
`skills workspace update --name "Studio" --email you@example.com` request a
|
|
800
|
+
fresh verification email and prompt for the code without showing its digits.
|
|
801
|
+
The current API selection still determines the server. These commands require
|
|
802
|
+
that server to support the additive customer-name routes; they do not enable
|
|
803
|
+
membership, billing or operator administration.
|
|
804
|
+
|
|
805
|
+
For automation, first request a fresh code through `skills auth login --email you@example.com --json`,
|
|
806
|
+
then pipe the code from your secure input source to the same command with
|
|
807
|
+
`--code-stdin --json`. Do not put verification codes in command arguments or
|
|
808
|
+
shell history. JSON/noninteractive updates require `--code-stdin`. Cancelling
|
|
809
|
+
an interactive prompt exits with status130 before verification.
|
|
810
|
+
|
|
811
|
+
`RemoteSkillsAuthClient.updateProfile(email, code, { displayName })` and
|
|
812
|
+
`updateCurrentWorkspace(email, code, { name })` use a fresh session without
|
|
813
|
+
replacing saved API keys or profile selection. `RemoteSkillsClient` exposes the
|
|
814
|
+
same name operations for an explicitly supplied interactive session. Servers
|
|
815
|
+
retain the final permission checks; ordinary API keys may be refused. MCP tools
|
|
816
|
+
`update_account_profile` and `update_workspace_name` accept a name, email and
|
|
817
|
+
fresh verification code, and return only the safe updated projection.
|
|
818
|
+
|
|
819
|
+
## Admin user-list authority
|
|
820
|
+
|
|
821
|
+
The `./admin-contract` user-list response retains a global identity whose default
|
|
822
|
+
workspace membership is absent or revoked. Its required `role` is `null` in that
|
|
823
|
+
case, and its `organizationId` remains the default workspace pointer. Null grants
|
|
824
|
+
no workspace authority. Consumers must handle it explicitly; an organization
|
|
825
|
+
filter lists active members of that workspace. Role assignment still requires a
|
|
826
|
+
concrete role and targets the default membership; a missing default membership
|
|
827
|
+
does not select a different workspace automatically. Active organization rosters
|
|
828
|
+
and role-mutation responses continue to require non-null roles.
|
|
829
|
+
|
|
830
|
+
## Current workspace roster on a compatible server
|
|
831
|
+
|
|
832
|
+
`skills workspace members --email you@example.com` requests fresh email
|
|
833
|
+
verification and reads one page of the current workspace roster. The selected
|
|
834
|
+
server requires a current owner/admin session; API keys and support
|
|
835
|
+
impersonation do not grant roster access. It never replaces saved credentials
|
|
836
|
+
or changes the selected profile.
|
|
837
|
+
|
|
838
|
+
For noninteractive use, request a code with the existing auth flow, then supply
|
|
839
|
+
it on stdin (never as a command argument):
|
|
840
|
+
|
|
841
|
+
```sh
|
|
842
|
+
skills workspace members --email you@example.com --code-stdin --limit 25 --json
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
JSON includes `organizationId`, `members`, and required `nextCursor` (null on the
|
|
846
|
+
last page). Pass a returned cursor unchanged with `--cursor` to read the next
|
|
847
|
+
page; limits are 1–100 with server default 50. Timestamps retain the server's
|
|
848
|
+
microsecond strings. Human output also includes a continuation cursor when one
|
|
849
|
+
exists. Empty pages are distinct from denied, unsupported or malformed responses,
|
|
850
|
+
which fail the command.
|
|
851
|
+
|
|
852
|
+
SDK callers with an authorized customer session can use
|
|
853
|
+
`RemoteSkillsClient.listWorkspaceMembers({ limit, cursor })`. For fresh email
|
|
854
|
+
verification, use `RemoteSkillsAuthClient.listWorkspaceMembers(email, code,
|
|
855
|
+
options)`. The MCP tool `list_workspace_members` takes `email`, `code`, and
|
|
856
|
+
optional `limit`/`cursor` and calls the same fresh-auth client.
|
|
857
|
+
|
|
858
|
+
## Change a current workspace membership
|
|
859
|
+
|
|
860
|
+
On a compatible server, use the exact `membershipId` and role from the roster:
|
|
861
|
+
|
|
862
|
+
```sh
|
|
863
|
+
skills workspace member role <membership-id> --role viewer --expected-role member --email you@example.com --code-stdin --json
|
|
864
|
+
skills workspace member remove <membership-id> --expected-role viewer --email you@example.com --code-stdin --json
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
Both commands use fresh verification and leave saved credentials and profiles
|
|
868
|
+
unchanged. Without `--code-stdin`, an interactive terminal requests and prompts
|
|
869
|
+
for a new code. JSON and noninteractive calls require a previously requested
|
|
870
|
+
code on stdin. The server enforces current owner/admin policy. Owners can change
|
|
871
|
+
roles while retaining an owner; admins can manage another member/viewer within
|
|
872
|
+
those two roles. Self-removal is unavailable.
|
|
873
|
+
|
|
874
|
+
`RemoteSkillsClient.setWorkspaceMemberRole(membershipId, { role, expectedRole })`
|
|
875
|
+
and `.removeWorkspaceMember(membershipId, { expectedRole })` accept an explicit
|
|
876
|
+
customer session. The corresponding `RemoteSkillsAuthClient` methods take
|
|
877
|
+
`email, code` before those arguments and obtain an ephemeral session. MCP tools
|
|
878
|
+
`set_workspace_member_role` and `remove_workspace_member` use the same client,
|
|
879
|
+
with required `membershipId`, `expectedRole`, `email`, `code`, and `role` for a
|
|
880
|
+
role change. API keys and support impersonation do not grant this authority.
|
|
881
|
+
|
|
882
|
+
A role result contains `{ organizationId, member, changed }`; removal contains
|
|
883
|
+
`{ organizationId, membershipId, removed: true, alreadyRemoved }`. Exact server
|
|
884
|
+
timestamps remain strings. An authorized already-applied role returns
|
|
885
|
+
`changed: false`; retrying removal of the same tombstone returns
|
|
886
|
+
`alreadyRemoved: true`. A later replacement membership has a different ID.
|
|
887
|
+
Stale expected-role conflicts require a roster refresh before another action.
|
|
888
|
+
The client never refreshes, changes the precondition, or retries automatically.
|
|
889
|
+
Known refusals expose a fixed message and code through `RemoteWorkspaceMemberError`;
|
|
890
|
+
unsupported routes remain errors. Invitations, workspace switching and leaving
|
|
891
|
+
your own workspace are separate capabilities.
|
|
892
|
+
|
|
893
|
+
### Workspace profiles
|
|
894
|
+
|
|
895
|
+
Discover the workspaces available to your account using a fresh verification code:
|
|
896
|
+
|
|
897
|
+
```sh
|
|
898
|
+
skills workspace list --email you@example.com --code-stdin --json
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
Pipe the six-digit code to stdin. Interactive terminal requests can omit
|
|
902
|
+
`--code-stdin` to request and enter a masked code. Discovery saves no credential.
|
|
903
|
+
The current marker identifies the workspace initially chosen by sign-in; it does
|
|
904
|
+
not change your account's default workspace.
|
|
905
|
+
|
|
906
|
+
To enroll a workspace, choose its exact membership ID from that list and name
|
|
907
|
+
the destination credential profile explicitly:
|
|
908
|
+
|
|
909
|
+
```sh
|
|
910
|
+
HASNA_PROFILE=team-b skills auth login --membership-id <membership-id> --email you@example.com --code-stdin --json
|
|
911
|
+
HASNA_PROFILE=team-b skills auth whoami --json
|
|
912
|
+
```
|
|
913
|
+
|
|
914
|
+
This fresh sign-in creates one ordinary CLI API key in that workspace, verifies
|
|
915
|
+
its identity, and saves it only in the named profile. Existing keys and other
|
|
916
|
+
profiles stay bound to their original workspaces. Viewer memberships cannot
|
|
917
|
+
create keys. Session JWTs are never saved. Remove injected API-key overrides
|
|
918
|
+
before enrolling a profile so that later commands use the saved credential.
|
|
919
|
+
A profile belonging to a different account requires a different profile name
|
|
920
|
+
or an ordinary replacement login. New accounts must finish ordinary account
|
|
921
|
+
login before workspace enrollment; the server's existing signup policy applies.
|
|
922
|
+
|
|
923
|
+
Named-profile account/workspace name updates, roster/member actions, and API-key
|
|
924
|
+
management retain that profile's live workspace identity through fresh OTP
|
|
925
|
+
verification. A revoked key, unavailable membership, or inconsistent profile
|
|
926
|
+
metadata refuses the operation; it does not fall back to the default workspace.
|
|
927
|
+
The CLI cannot change your parent shell: keep `HASNA_PROFILE=team-b` on subsequent
|
|
928
|
+
commands or configure it explicitly in that shell. Existing MCP fresh-auth
|
|
929
|
+
account, member and key tools retain the same named profile authority for each
|
|
930
|
+
invocation. Changing an MCP host’s selected profile
|
|
931
|
+
through a tool remains a separate follow-up.
|
|
932
|
+
|
|
933
|
+
If enrollment reports that key issuance was attempted but not confirmed, inspect
|
|
934
|
+
the selected profile and workspace keys before retrying. A lost response can
|
|
935
|
+
still have created a server key; the CLI does not retry issuance automatically.
|