Docs: marketplace, and clean up new-code warnings/lints
CLAUDE.md gets a Marketplace subsection under Key Conventions (the sync script is app-embedded and re-uploaded on every sync, never baked into container/ — pre-flight F9) and the Settings export/import section now covers marketplace account tokens traveling in ExportedSecrets and the import preview's warning on global hook and plugin installs. HOW-TO-USE.md gets a Marketplace section (placed after Shared Claude Authentication) with its Table of Contents entry (pre-flight N13). The spec doc's stale keychain service name, gh-login flags and upload_bytes_to_container signature are amended to match the shipped code (pre-flight N10). Also fixes the new marketplace code's remaining build/clippy warnings: BTreeMap/Sha256/Digest imports in tree.rs gated behind #[cfg(test)] (their only uses are on MemTree, already test-only), the unused `pub use marketplace::*` glob re-export dropped from models/mod.rs, gh_login::strip_ansi marked #[cfg(test)] (production streams through AnsiStripper instead), and four clippy lints in marketplace test code (double_ended_iterator_last, cloned_ref_to_slice_refs x2, single_match). Flushes the unresolved getMarketplaceSyncReport promise in MarketplaceSection.test.tsx's "opens the Marketplace filtered to this project" test to remove its act() warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@ publishing to a marketplace from inside Triple-C, a separate OS window for the m
|
||||
(shared Claude token, gateway keys). Project secrets are restricted to `PROJECT_SECRET_KEYS`.
|
||||
- Container start: `commands/project_commands.rs` `start_project_container` runs
|
||||
`docker::sync_bedrock_credentials` after start (≈:1448) — the pattern the marketplace sync follows.
|
||||
- Exec/upload: `docker/exec.rs` `upload_bytes_to_container(container_id, dest_dir, file_name, data)`,
|
||||
- Exec/upload: `docker/exec.rs` `upload_bytes_to_container(container_id, dest_dir, file_name, data, mode)`,
|
||||
`exec_oneshot_streams_as(container_id, user, cmd, env)`, `create_attached_exec_as(…, tty, user)`.
|
||||
Container user is addressed as `"claude"`. Constant-script + env-data rule: header of
|
||||
`commands/inspect_commands.rs`.
|
||||
@@ -141,10 +141,10 @@ pub marketplace_installs: Vec<MarketplaceInstall>, // project-only additions
|
||||
pub marketplace_disabled: Vec<MarketplaceItemRef>, // (marketplace_id, kind, key) opted out
|
||||
```
|
||||
|
||||
**Secrets.** Token and GhContainer accounts keep their token in the keychain as
|
||||
`marketplace-account:<id>` (new global helpers in `secure.rs` alongside the gateway ones).
|
||||
GhHost accounts store nothing: every fetch runs `gh auth token --hostname <host>` so a later
|
||||
`gh auth refresh`/logout on the host is honoured. Deleting an account deletes its entry.
|
||||
**Secrets.** Token and GhContainer accounts keep their token in the keychain, one service per
|
||||
account (`triple-c-marketplace-account-<id>`; new global helpers in `secure.rs` alongside the
|
||||
gateway ones). GhHost accounts store nothing: every fetch runs `gh auth token --hostname <host>`
|
||||
so a later `gh auth refresh`/logout on the host is honoured. Deleting an account deletes its entry.
|
||||
|
||||
**Effective set for a project** (pure function, unit-tested):
|
||||
`(global − project.marketplace_disabled) ∪ project.marketplace_installs`, keyed by
|
||||
@@ -161,7 +161,13 @@ the next sync removes those items from containers; the UI says so before the mar
|
||||
removed and offers "Forget" to drop the stale entries.
|
||||
|
||||
**Export/import.** Accounts (without secrets), marketplaces and install lists go into the existing
|
||||
export; account tokens follow the existing encrypted-secrets policy of `settings_export.rs`.
|
||||
export as ordinary `AppSettings` fields; account tokens follow the existing encrypted-secrets
|
||||
policy of `settings_export.rs` (`ExportedSecrets::marketplace_account_tokens`, keyed by account
|
||||
id, restored to the keychain before the settings replace). Because the import is untrusted input
|
||||
and not merely a restore, imported marketplaces and installs are validated on import the same way
|
||||
the add-marketplace/install commands validate them (host, key pattern, pinned-commit shape), and
|
||||
the confirmation preview warns whenever the import contains a global hook or global plugin install
|
||||
— those skip the hook-confirm step an install from the Marketplace tab shows.
|
||||
|
||||
## 3. Fetching and signing in
|
||||
|
||||
@@ -186,11 +192,14 @@ Hooks' diffs always show the rendered commands.
|
||||
logged in, tell the user to run `gh auth login` (we do not drive the host's gh interactively).
|
||||
`gh api user --jq .login` for the display name.
|
||||
- **GitHub via `gh` in a container** (no host `gh`): user picks a running project; Triple-C runs
|
||||
`gh auth login --hostname <host> --web --git-protocol https --scopes repo` in an attached pty
|
||||
exec with `GH_CONFIG_DIR=$(mktemp -d)`, surfaces the one-time code and URL in a dialog (same
|
||||
shape as `ClaudeAuthModal`), then runs `gh auth token` with the same config dir, stores the
|
||||
token in the keychain and `rm -rf`s the dir. Cancel tears the exec down. Nothing persists in the
|
||||
container, so Claude in that container is not logged into the user's GitHub.
|
||||
`gh auth login --hostname <host> --web --git-protocol ssh --skip-ssh-key --scopes repo` in an
|
||||
attached pty exec, with `GH_CONFIG_DIR` and `GIT_CONFIG_GLOBAL` both pointed at a temp dir
|
||||
(`$(mktemp -d)`) — `--git-protocol ssh --skip-ssh-key` avoids gh's "Authenticate Git with your
|
||||
GitHub credentials?" prompt, which under `https` would otherwise write a credential helper into
|
||||
`~/.gitconfig`. It surfaces the one-time code and URL in a dialog (same shape as
|
||||
`ClaudeAuthModal`), then runs `gh auth token` with the same config dir, stores the token in the
|
||||
keychain and `rm -rf`s the dir. Cancel tears the exec down. Nothing persists in the container,
|
||||
so Claude in that container is not logged into the user's GitHub.
|
||||
- **Token**: pasted once, validated via the host's "who am I" API
|
||||
(GitHub `GET /user`, Gitea `GET /api/v1/user`, GitLab `GET /api/v4/user`; unknown host → test
|
||||
`ls-remote`-equivalent fetch), stored in the keychain. The token is never returned to the frontend.
|
||||
|
||||
Reference in New Issue
Block a user