Skip to content

feat: landing guide, a third seeded role, a staff order list — and the docs to match - #64

Merged
bgard68 merged 3 commits into
mainfrom
claude/professional-design-styling-2fa2c5
Aug 19, 2026
Merged

feat: landing guide, a third seeded role, a staff order list — and the docs to match#64
bgard68 merged 3 commits into
mainfrom
claude/professional-design-styling-2fa2c5

Conversation

@bgard68

@bgard68 bgard68 commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Two commits: the app change, then the documentation that had drifted behind it.

The app

A landing page at /. Everyone arrives at a plain-language guide instead of being
dropped into a catalog with no explanation. It states up front that no payment is ever
taken
— the mock gateway never asks for a card, and the Stripe path is test-mode only —
hands out the three demo accounts with copy buttons and a can/cannot list for each role,
points at /orders for the receipt (emails go to the log on the hosted demo, so there is
nothing to miss), and links into the store. The catalog moved to /store.

A Manager account, seeded. The ManageCatalog policy has existed since the catalog
work but no seeded account could exercise it, so a reviewer could only ever see Customer
and Administrator. manager@widgetworks.demo closes that: catalog and order fulfilment,
but not delete and not user management.

A staff order list (GET /admin/orders). The admin screen could only look an order up
by GUID, and nobody has a GUID to hand — so orders were effectively invisible to the
people whose job is fulfilling them. The list is now the entry point; selecting a row opens
the detail and status controls.

The docs

The tax chapter described the calculator but never showed the arithmetic, the coverage, or
who bears the charge. It now carries the formula (taxable = subtotal — shipping is not
taxed
), a worked example across CA / OR / an unknown state, the away-from-zero rounding
and why it differs from .NET's default, the full 51-entry rate table generated from
StaticStateTaxRateProvider, and the quote / tax-info endpoints. Shipping tiers are
written down beside it, since they are the other half of the total.

The bugs chapter gains rows 12–32 — the refresh-token race, the broken HTML email part, the
compose keys that never reached the container, the startup crash loop that burns free-tier
quota, the SPA fallback and CSP, the order list nobody could reach, and the provisioning
failures (a Windows batch shim, MSYS path rewriting, a PowerShell automatic variable, an
action SHA that didn't exist, an OIDC subject that doesn't match its documentation, and a
required check that could never pass).

Everything else was drift: the Manager account undocumented, / no longer the catalog,
Mailpit running in compose while the runbook told you to start your own, the deploy gate
undescribed, and a README LICENSE link pointing at a file that does not exist — which on a
public repo reads as a license that was never granted. It now says so plainly.

Deployment

This touches src/** and web/**, so merging fires both deploys — each gated on the
full test suite (backend units, frontend units, API smoke test) before anything uploads.

🤖 Generated with Claude Code

bgard68 and others added 3 commits August 19, 2026 06:42
Adds deploy-api.yml and deploy-web.yml, each triggered by an allowlist of paths
rather than paths-ignore, so scope is explicit: src/tests/solution files deploy
the API, web/** deploys the SPA, and a docs or markdown change matches neither
and deploys nothing.

Both call a new reusable test-suite.yml and declare needs: tests, so nothing
reaches Azure unless backend units, frontend units and the end-to-end smoke test
all pass for that exact commit. The suite lives in one file so the two deploys
cannot drift on what 'tests passed' means. The web deploy is gated on the smoke
test too — a SPA is useless against a broken API.

The API job publishes Release to a directory outside the workspace and audits it
before deploying: any .cs, .csproj, .sln, .env, compose file, or
.git/node_modules/src/web/tests/docs directory fails the run, and the app dll
and appsettings.json must be present. It then polls /health and stops the web
app on a 503, because a crash-looping F1 app silently consumes the 60
CPU-minutes/day allowance.

Azure auth is OIDC — id-token: write and no stored credential. Every action is
pinned to a full commit SHA, each verified to exist against the GitHub API;
one I had written from memory was wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Everyone now lands on a guide at / and the store moves to /store. A working
storefront is confusing without knowing it is a demo, that nothing can charge
you, and which account to use, so the guide answers those first and links into
the store from several places.

The guide leads with the payments question because it is the one that decides
whether a visitor trusts the site: checkout runs a mock gateway, no card details
are collected, no processor is contacted, and a Stripe configuration is
restricted to test mode.

Three roles existed but only two were seeded, so nothing demonstrated what
ManageCatalog actually buys you. DbSeeder now creates a Manager as well, and the
guide spells out for each role what it can and cannot do — the interesting line
being that a Manager may restock and hide a widget but not retire one.

Staff could not find an order at all: admin had only lookup-by-GUID, and nobody
has a GUID to hand. Adds GET /admin/orders with a recent-orders list, and rebuilds
the admin page around selecting from it. The item rows are loaded rather than
skipped — OrderSummary derives its item count from them, and an initial
optimisation reported every order as empty.

Receipts work on the free tier without a mail server: the hosted demo writes
email to the log, so the order detail page carries the same line items, totals,
payment and tracking, and now prints as a receipt. The print stylesheet drops the
chrome and collapses the columns.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The tax chapter said what the calculator did but never showed the arithmetic, the
coverage, or who bears the charge — the three things a reader actually asks. It now
carries the formula (taxable = subtotal; shipping is not taxed), a worked example
across CA / OR / an unknown state, the rounding mode and why it differs from .NET's
default, the full 51-entry rate table generated from the source, and the quote and
tax-info endpoints that expose it without placing an order. Shipping tiers are
written down alongside it, since they are the other half of the total.

The bugs chapter gains rows 12-32: the refresh-token race, the broken HTML email
part, the compose keys that never reached the container, the startup crash loop that
burns free-tier quota, the SPA fallback and CSP, the order list nobody could reach,
and the provisioning failures — a Windows batch shim, MSYS path rewriting, a
PowerShell automatic variable, a non-existent action SHA, an OIDC subject that
doesn't match its documentation, and a required check that could never pass.

Everything else was drifting from the code: the Manager account was seeded but
undocumented, the landing page had replaced the catalog at /, Mailpit was running in
compose while the runbook still told you to start your own, and the deploy gate was
undescribed. The README's LICENSE link pointed at a file that does not exist, which
on a public repo reads as a license that isn't granted; it now says so plainly.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

OpenSSF Scorecard

PackageVersionScoreDetails
actions/actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 🟢 7
Details
CheckScoreReason
Maintained🟢 1024 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Code-Review🟢 10all changesets reviewed
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
Packaging⚠️ -1packaging workflow not detected
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Security-Policy🟢 9security policy file detected
SAST🟢 10SAST tool is run on all commits
Branch-Protection🟢 6branch protection is not maximal on development and all release branches
actions/actions/setup-dotnet 67a3573c9a986a3f9c594539f4ab511d57bb3ce9 🟢 6.6
Details
CheckScoreReason
Binary-Artifacts🟢 10no binaries found in the repo
Maintained🟢 1015 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 9SAST tool is not run on all commits -- score normalized to 9

Scanned Files

  • .github/workflows/test-suite.yml

@bgard68
bgard68 merged commit 3433a6c into main Aug 19, 2026
7 checks passed
@bgard68
bgard68 deleted the claude/professional-design-styling-2fa2c5 branch August 19, 2026 13:16
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.

1 participant