* Clarify extension catalog trust model in docs, help, and messaging (#4176)
Extension catalog management gave no explanation of why the community
catalog is discovery-only, and the install-error text nudged users to
flip a discovery catalog to install_allowed — exactly the wrong move.
- Docs: add a "discovery-only vs. install sources" trust-model section,
document `add --from <url>` as the lightweight vetted-install path, and
stop implying you should make community installable.
- Help: expand the `catalog` app and `--install-allowed` help to state the
vetting intent instead of bare mechanics.
- Messaging: rewrite the not-installable errors in `add`, `search`, and
`info` to point at `--from` and self-curated catalogs, and to say
explicitly not to flip a discovery-only catalog to install_allowed.
- `catalog list` now prints trust-model guidance when a discovery-only
catalog is active.
- Tests cover the new list guidance (present/absent).
Deliberately does not add a verb to toggle install_allowed on an existing
catalog: discovery-only is a security boundary, not an inconvenience.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a86c498e-f129-4422-9983-d1a33513fd4d
* Address PR review: copy-pasteable install hint and accurate --from warning (#4176)
- The discovery-only "install directly" hint used the user-typed argument,
which can be a display name with spaces (resolved via search) and would
break when copied as a shell command. Emit the resolved catalog ID
(ext_info['id']) instead. Added a regression test.
- The `--from` untrusted-source warning claimed the URL was "not listed in
any of your configured extension catalogs", which is false for a URL
copied from a discovery-only catalog — the exact flow this PR documents.
Reword it to state the install is bypassing trusted (install-allowed)
catalogs, which is accurate regardless of discovery-catalog membership.
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a86c498e-f129-4422-9983-d1a33513fd4d
* Harden install hints against catalog-controlled IDs; expose archive URL (#4176)
Second review round on #4177.
Shell-safety: catalog entry IDs (especially from discovery-only catalogs)
are not validated during catalog merge, and rich.markup.escape only
neutralizes Rich markup, not shell metacharacters. A malicious ID like
`foo; rm -rf ~` was interpolated into the `specify extension add ... --from`
command we encourage the user to copy. Add `_command_safe_id`, which only
emits an ID matching the manifest rule `^[a-z0-9-]+$` (via
VALID_EXTENSION_ARTIFACT_NAME_PATTERN) and otherwise falls back to a literal
`<extension-id>` placeholder. Applied to every suggested command in `add`,
`search`, and `info`.
Discoverability: the documented `--from <archive-url>` flow gave no CLI path
to obtain the URL. `extension info` now prints the candidate `download_url`
for a discovery-only entry (clearly flagged as needing vetting), and the docs
show `extension info <name>` as the way to get the archive URL.
Tests cover the resolved-ID hint, the unsafe-ID neutralization, and pass the
full extensions + CLI suites (635).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a86c498e-f129-4422-9983-d1a33513fd4d
* Reject leading-hyphen catalog IDs; test info archive-URL branch (#4176)
Third review round on #4177.
_command_safe_id: an ID like `--force` satisfies the manifest character rule
`^[a-z0-9-]+$` but Typer parses a leading hyphen as an option rather than the
positional extension argument, so an untrusted catalog could still yield a
non-copyable or option-altering suggested command. Reject a leading hyphen and
fall back to the `<extension-id>` placeholder.
Tests: cover the new `extension info` discovery-only branch that surfaces the
candidate `download_url` (plus the no-URL fallback), and the leading-hyphen
rejection. Full extensions suite green (528).
Assisted-by: GitHub Copilot (model: Claude Opus 4.8, supervised)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a86c498e-f129-4422-9983-d1a33513fd4d
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a86c498e-f129-4422-9983-d1a33513fd4d
* docs: document missing flags and integrations
* docs: remove invalid --refresh-shared-infra from upgrade command
* docs: address PR feedback for extension and integration flags
* docs: reorder extension add options to match CLI help
* docs: add workflows reference, reorganize into docs/reference/, and add --version flag
- Move integrations.md, extensions.md, presets.md into docs/reference/
- New docs/reference/workflows.md: command reference for all workflow
commands, built-in SDD Cycle workflow with Mermaid diagram, step types,
expressions, input types, state/resume, and FAQ
- Rename workflow input feature_name to spec with prompt 'Describe what
you want to build' to match speckit.specify command terminology
- Add --version / -V flag to root specify command with tests
- Update docs/toc.yml, README.md links, and docs/upgrade.md cross-reference
to use reference/ paths
- Add workflow command to README CLI reference table
* docs: update speckit_version requirement to >=0.7.2 in workflow example