Skip to content

Include API version in issue summary (#991) - #992

Merged
AcoPiper merged 3 commits into
mainfrom
AcoPiper/issue-991
Sep 8, 2026
Merged

Include API version in issue summary (#991)#992
AcoPiper merged 3 commits into
mainfrom
AcoPiper/issue-991

Conversation

@AcoPiper

@AcoPiper AcoPiper commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

bootroot registrar issue --json has always carried api_version, but the prose summary printed without --json reported only the identity and the expiry — so an operator who did not ask for a body could not tell which surface version minted the credential.

The issue response's api_version is now passed to the human-summary formatter, and both localized templates render it. The wire token is protocol rather than prose: bootroot.registrar.v1 is substituted unaltered in English and Korean alike, with only the surrounding sentence translated. No CLI flag was added, and issuance, publication, identity composition and the endpoint protocol are untouched. The English and Korean CLI manuals and the changelog entry now describe the non-JSON summary alongside the body.

Two gaps in the surrounding coverage are closed alongside it. The JSON body is now held to being exactly api_version, identity, not_after and no other key, so a field silently gained or renamed fails rather than passing on the strength of the three a caller already knows. And neither issue path held the reported expiry to the certificate it describes: the JSON path asserted only that the instant had not passed yet — any future instant satisfied that — and the prose path did not read it at all. Each now compares the reported value against the notAfter of the leaf the run actually published.

Closes #991

Part of #989

Test plan

  • tests/bootroot_registrar.rs::issue_without_json_summarizes_what_it_issued asserts stdout carries the exact bootroot.registrar.v1 token, the composed identity, and an RFC 3339 expiry equal to the published leaf's notAfter.
  • src/i18n.rs::registrar_surface_summaries_carry_the_api_version_in_every_locale renders both the capabilities and issue summaries in en and ko, asserting every field substitutes and no placeholder is left behind.
  • tests/bootroot_registrar.rs::issue_writes_a_recognized_registrar_client_credential asserts the JSON body's key set is exactly the three fields, in their existing wire spellings.
  • cargo test — full suite green.
  • cargo fmt -- --check --config group_imports=StdExternalCrate, cargo clippy --all-targets -- -D warnings, RUSTDOCFLAGS=-D warnings cargo doc --no-deps --document-private-items.
  • markdownlint-cli2 "**/*.md" and ./scripts/check-docs.sh (mkdocs build --strict plus the theme assertions) for the docs/en/cli.md, docs/ko/cli.md and CHANGELOG.md changes.
  • scripts/validate-deploy-compose.sh, validate-compose-instance-names.sh, validate-e2e-openssl-compat.sh, validate-e2e-leftover-check.sh, validate-e2e-run-scope.sh.
  • scripts/preflight/ci/e2e-matrix.sh — not run. The change is confined to the prose rendered by registrar issue, its localization tables and its integration coverage; no E2E script invokes that verb, and the Docker lifecycle, rotation, service add/verify, daemon and config paths are untouched. CI's Docker E2E jobs gate it.

`registrar issue --json` carries `api_version`, and the provisioning
surface's contract holds the prose summary to the same three fields.
It reported only the identity and the expiry, so an operator who did
not ask for a body could not tell which surface version minted the
credential without re-running the command.

The wire token is protocol rather than prose: both locales render
`bootroot.registrar.v1` unaltered, and a unit test holds each template
to substituting all three values.

Closes #991
Part of #989
The surface's contract is read by field name, so a body that gains or
renames one is a wire change even when the three the caller knows
still answer. The JSON coverage asserted each of those three and never
the set, leaving that silent.

Part of #991
Both issue paths asserted only that the expiry they report has not
passed yet. Any future instant satisfies that, so a summary or a body
reporting the issuer's lifetime, a stale value or a constant would pass
while telling the caller the wrong thing about the credential it just
received.

The expiry is read off the leaf, so the assertion can be too: compare
what was printed against the notAfter of the certificate the run
published.

Part of #991
@AcoPiper

AcoPiper commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

[Reviewer Round 1]

Verdict: approve — no findings.

The change correctly routes IssueResponse.api_version into the non-JSON formatter at src/commands/registrar.rs, and both English and Korean templates preserve it as a substituted wire token (en.rs, ko.rs).

Coverage is meaningful: the CLI integration test asserts the exact API token, composed identity, and published leaf’s RFC 3339 expiry (tests/bootroot_registrar.rs); localization coverage exercises both locales and all three issue-summary fields (src/i18n.rs). JSON output remains unchanged and is now held to its exact three-field shape.

PR hygiene is also in order: it closes #991, carries only the inherited Part of #989, includes a test plan, and has no review-thread issue creation.

@AcoPiper

AcoPiper commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

[Review Verdict Round 1: APPROVED]

@AcoPiper

AcoPiper commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Suggested squash commit

Title

Report the surface version in the issue summary

Body

`bootroot registrar issue --json` has always carried `api_version`,
but the prose summary printed without `--json` reported only the
identity and the expiry, so an operator who did not ask for a body
could not tell which surface version minted the credential.

Pass the issue response's `api_version` to the human-summary
formatter and render it in both localized templates. The token is
protocol rather than prose: `bootroot.registrar.v1` is substituted
unaltered in English and Korean alike, with only the surrounding
sentence translated.

Close two gaps in the surrounding coverage alongside it. The JSON
body is now held to being exactly `api_version`, `identity` and
`not_after`, so a field silently gained or renamed fails rather than
passing on the strength of the three a caller already knows. And
neither issue path held the reported expiry to the certificate it
describes — the JSON path asserted only that the instant had not
passed yet, and the prose path did not read it at all — so each now
compares the reported value against the `notAfter` of the leaf the
run actually published.

Closes #991
Part of #989

@AcoPiper
AcoPiper merged commit 527a03d into main Sep 8, 2026
23 checks passed
@AcoPiper
AcoPiper deleted the AcoPiper/issue-991 branch September 8, 2026 13:46
@AcoPiper AcoPiper mentioned this pull request Sep 8, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Include API version in issue summary

1 participant