freedomofpress / freedomofpress/webcat-cli
feat request: `webcat init` to guide enrollment onboarding
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 2
- PR merge metrics
- No merged PRs in 30d
Description
I am but a hapless developer
After several attempts to enroll a website in WEBCAT, following the existing docs, I find myself wishing for more guardrails in the CLI tooling. The docs contain this example command:
npx webcat enrollment create \
--type sigstore \
--community-trusted-root \
--identity alice@example.com \
--issuer https://token.actions.githubusercontent.com \
--build-signer-uri https://github.com/acme/repo/.github/workflows/release.yml@refs/heads/main \
--claim 1.3.6.1.4.1.57264.1.11=platform-hosted \
--max-age 3600
That command confuses me. First off, I'm surprised that the webcat CLI is not the initial element on the invocation—should I be using npx to run webcat? I want to install the webcat CLI, and then use it—thus https://github.com/freedomofpress/webcat-cli/issues/11, so let's dismiss that concern for now.
Next, I don't know how to choose between sigsum and sigstore. The first time I've heard either of those words was from reading the WEBCAT documentation. In general, I prefer to control private key material myself, rather than offloading the trust to Github Actions, so after much comparison, I believe sigsum is the right approach for me. I suggest that the CLI default to sigsum. In general, I suggest we identify defaults for all the settings, and allow developers to customize them.
OK, now I know that I want sigsum, so it's time to get started. The docs say:
To learn more about Sigsum and how to write a policy, see Sigsum’s Getting Started guide.
But I don't want to learn how to write a Sigsum policy—I want to enroll my site in WEBCAT! As a developer, I expect the WEBCAT CLI to template out a suitable policy for me, because the tool knows far better than I do what the heck a Sigsum policy even is.
Only after reading through several Sigstore [sic] examples in the docs, do I finally arrive at a verbose example of how to use Sigsum:
verbose example of sigsum usage
# 1) Prepare demo keys
mkdir -p keys
sigsum-key generate -o keys/key1
sigsum-key generate -o keys/key2
HEX1=$(sigsum-key to-hex -k keys/key1.pub)
HEX2=$(sigsum-key to-hex -k keys/key2.pub)
# 2) Create trust policy and app config
cat > trust_policy <<'EOF'
log 4644af2abd40f4895a003bca350f9d5912ab301a49c77f13e5b6d905c20a5fe6 https://test.sigsum.org/barreleye
witness poc.sigsum.org/nisse 1c25f8a44c635457e2e391d1efbca7d4c2951a0aef06225a881e46b98962ac6c
witness rgdd.se/poc-witness 28c92a5a3a054d317c86fc2eeb6a7ab2054d6217100d0be67ded5b74323c5806
group demo-quorum-rule any poc.sigsum.org/nisse rgdd.se/poc-witness
quorum demo-quorum-rule
EOF
cat > webcat.config.json <<'EOF'
{
"app": "https://github.com/element-hq/element-web",
"version": "1.12.3",
"default_csp": "default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self' 'wasm-unsafe-eval'; img-src * blob: data:; connect-src * blob:; font-src 'self' data: ; media-src * blob: data:; child-src blob: data:; worker-src 'self'; frame-src blob: data:; form-action 'self'; manifest-src 'self'; frame-ancestors 'self'",
"default_index": "index.html",
"default_fallback": "/error.html",
"wasm": ["8A7Ecx-qI7PnFNAOiNTRDi31wKQn06K0rm41Jv3RTvc"],
"extra_csp": {}
}
EOF
# 3) Produce enrollment and manifest
TMPDIR=$(mktemp -d)
echo index > "$TMPDIR/index.html"
echo error > "$TMPDIR/error.html"
npx webcat enrollment create \
--policy-file trust_policy \
--threshold 1 \
--max-age 15552000 \
--cas-url https://cas.demoelement.com \
--signer "$HEX1" \
--signer "$HEX2" \
--output enrollment.json
npx webcat manifest generate \
--policy-file trust_policy \
--config webcat.config.json \
--directory "$TMPDIR" \
--output manifest_unsigned.json
npx webcat manifest sign \
--policy-file trust_policy \
-i manifest_unsigned.json \
-k keys/key1 \
-o manifest.json
# 4) Bundle and verify
npx webcat bundle create \
--enrollment enrollment.json \
--manifest manifest.json \
--output bundle.json
npx webcat manifest verify bundle.json
Grapping with the above wall of cryptic commands is usually the point during my enrollment attempt where I get confused, lose steam, and say to myself, "You know, maybe I should do something else right now—I'll check back on WEBCAT tomorrow." Is this lack of fortitude an indictment on my individual attention economy? Yes! Is this attribute perhaps common among the set of developers we'd like to see get involved in WEBCAT? I daresay yes to that, too.
Help me, webcat-cli, you're my only hope
As a developer, I embrace CLI tooling to help me accomplish tasks. I don't think the existing webcat-cli goes far enough in helping me to cobble together the various manifests that I need to enroll my site. The shape I wish for is something like:
webcat init
which then walks me through an interactive guide to configure my setup. Ideally, those choices—like sigsum over sigstore—would persist somewhere, either in my home directory like ~/.config/webcat/config.toml or else in-repo via e.g. webcat.toml.
In particular, as hard as it is for me to wade through the steps to generate key material, manifests, and bundles, both the docs and the tooling don't help by pointing to next steps of actually uploading these materials to the relevant docroot.
How I want it
Here's an example of how such an init tool could work.
example terminal session of `webcat init`
❯ webcat init
┌ WEBCAT — site enrollment setup
│
◇ What is the origin you are enrolling?
│ https://ruin.ist
│
◇ Version string for this release
│ 0.1.0
│
◇ Which Sigsum trust policy?
│ sigsum-test-2025-3
│
◇ How many signing keys?
│ 2
│
◇ How many signatures are required to accept a manifest?
│ 1
│
◇ Content Security Policy
│ Start from a preset — Static site — no WebAssembly, no framing
│
◇ Content Security Policy ──────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
│ default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; │
│ manifest-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none' │
│ │
│ ✔ policy satisfies WEBCAT's CSP restrictions │
│ 1 ok, 0 warnings, 0 errors │
│ │
├────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
│
◇ How long may a signed manifest stay valid? (max_age)
│ 180d
│
└ wrote webcat.config.json
wrote trust_policy
wrote .well-known/webcat/enrollment.json
wrote WEBCAT-NEXT-STEPS.md
Next steps — full detail in WEBCAT-NEXT-STEPS.md
1. Serve .well-known/webcat/ at https://ruin.ist/.well-known/webcat/
2. Send this response header, byte for byte:
Content-Security-Policy: default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; manifest-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'
3. Publish this DNS record, so the Sigsum log accepts your submissions:
_sigsum_v1.ruin.ist. IN TXT "77ec57d8c036c2bdeb8e1ecdac76000166d547a87bc349025a21b4af46dc641b"
4. Build the site, then generate, sign, and bundle the manifest — step 4 of the checklist
5. Verify: webcat site check https://ruin.ist --config webcat.config.json
6. Enroll: https://enroll.webcat.tech/
The core conveniences as I see them:
- Any unset but required CLI flag has a sane default, presented to me as a multiple-choice list.
- The default choices are opinionated, and therefore give me a foothold—e.g. sigsum over sigstore, or test policy over production log usage.
- Absolutely no copy/pasting of JSON snippets from the documentation website: the tool generates templates for me.
- Guiding language describing next steps that I must take to complete the process.
Most of that list seems relatively straightforward to implement, although we could quibble about what constitutes a "sane default" for many settings. Less clear to me are problems like:
- Should we have a durable config (e.g.
~/.config/webcat/config.toml) to store user preferences? - Should we store key material somewhere known, e.g.
~/.config/webcat/keys/sigsum1.key? - Can I use pre-existing ed25519 key material, stored on a hardware token or elsewhere? (I gather not, but the docs should be clear about this.)
- Should we programtically inspect the remote CSP via the built-in tooling, and warn about problems prior to enrollment? (I'd say yes, but it's more moving parts.)
Input on developer experience
I'd appreciate more frank descriptions of first-time interaction with the webcat enrollment process, in order to inform our approach to adding guard rails, and in general making the process more pleasant and less onerous. Finally, thank you for indulging the tone of this post: it's a bit contrived to struggle so much, but for me, frustration is often the first step toward empathy, and therefore better software interfaces.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the existing enrollment create, manifest generate/sign, bundle create, and manifest verify commands described in the issue, along with the documented enrollment flow. Define the scope of webcat init before implementation: interactive defaults, generated configuration and enrollment files, and clear next steps for serving, signing, verifying, and enrolling.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, developer-experience
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100