Operator pages show a failed read as an empty or settled answer instead of an error #207
Open
opened 2026-10-09 16:03:03 +00:00 by cgalo5758
·
1 comment
Labels
Clear labels
accessibility
area/billing
area/catalog
area/discourse
area/domains
area/entitlements
area/fedwiki
area/identity
area/integrations
area/licensing
area/member-ui
area/meta
area/operator-ui
area/ops
area/testing
duplicate
good-first-issue
invalid
privacy
security
upstream
wontfix
A barrier for people using assistive technology or a keyboard alone.
The Stripe mirror, checkout, subscriptions, invoices, fulfillment.
Products, prices, plan ladders, purchasability.
The Discourse integration.
The domains registry, claims, placements, the certificate ask.
Entitlement sets, rules, grants, pools, provisioning.
The Federated Wiki integration and farm sync.
Sign-in, sessions, persons, organizations, workspaces, roles.
The provider registry, outbox and webhooks in general.
Licenses, the contributor agreement, SPDX headers.
Member pages.
The repository itself, its contributing guide, CI, the tracker and the workflow.
Operator pages, forms, lists, the design system.
Deployment, configuration, migrations, workflows, instance settings.
The test stack, screens, lint, walkthroughs.
Closed because another issue already covers it.
Small, self-contained, and explained enough to be a first contribution.
Closed because it is not a ticket for this repository.
Touches what a person's data reveals.
Touches authentication, authorization, secrets or data exposure.
Waits on another repository or project before it can move.
Closed because it will not be done, with the reason in the last comment.
kind
bug
The software does something other than what it promises; closed when it again does what it promises.
kind
debt
Code, tests or tooling to clean up with nothing visible changing; closed when they are cleaner.
kind
design
A question to settle before work can be defined; closed when the decision is written down.
kind
docs
Documentation that is wrong or missing; closed when it says the right thing.
kind
enhancement
Something the software does not do yet; closed when it does.
priority
critical
Blocks the active milestone or harms members now.
priority
high
Next in line inside the active milestone.
priority
low
Inside the active milestone, when nothing else is left.
priority
medium
Inside the active milestone, after the high ones.
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: wiki-cafe/member-console#207
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What happens
This is the operator side of #197. Several operator pages treat a failed database read as an empty answer. The section shows its empty state, or a verdict built from the missing rows, and nothing on the page says a read failed. Most of these reads leave no log line.
Products list and product page.
buildProductListViewModelslogs each failed batch read and builds the rows as if the read had returned nothing:The product page's readiness panel (
loadProductEditDataResult,loadProviderReadinessRows) does the same with its own reads. After a failed mapping read it says the price is not registered with Stripe and offers Sync to Stripe. After a failed ladder read it says "Not a tier on any ladder."Organization page.
loadOrgEnrollmentDatashows "Organization not found" for any error reading the organization, including a database fault.subscriptionHeldLaddersdrops the ⚠ warning that a grant would replace a tier a subscription pays for.None of these reads is logged.
Grants page and the organization's grants ledger.
buildGrantViewModelsdrops name-read errors without logging them.Plan topology and the plan ladders list.
loadPlanTopologyDatadiscards the errors of the reads it makes for each ladder:loadPlanLaddersPageDatashows 0 tiers and 0 organizations when a ladder's reads fail, and offers Delete, which the delete handler then refuses after counting again.Billing. The invoice page (
loadOperatorInvoiceDetailData) answers 404, "There is no operator page at …", for any failed read of the invoice, not only a missing invoice, and logs nothing. The billing lists hide rows recorded in the Stripe mode (test or live) that the configured key is not in. WhenresolveEnvFilterfails to read which rows those are, it logs a warning and hides nothing. The other mode's rows then appear among the key's own, unmarked, and no line says they are there.Some sections already report their own failure. On the organization page, Tier changes, Members, Grants and Entitlement changes show a load error in place of their content. The product page answers "Could not load this product right now. Try again." when the product read fails.
What should happen
When a read fails, the error is logged and the page reports the failure where the answer would have appeared:
Where
internal/server/operator_products.go:buildProductListViewModels,loadProductEditDataResult,loadProviderReadinessRowsinternal/server/operator_enrollment.go:loadOrgEnrollmentData,subscriptionHeldLaddersinternal/server/operator_partials.go:buildGrantViewModelsinternal/server/operator_topology.go:loadPlanTopologyDatainternal/server/operator_plan_ladders.go:loadPlanLaddersPageDatainternal/server/operator_billing.go:loadOperatorInvoiceDetailData,resolveEnvFilterThe batch name reads #10 asks for would replace the per-row name reads on the grants and organization pages, so the name cases can be fixed with that work.
Why it matters
During a passing database fault, an operator can be told any of these:
The operator can act on these. For example, they can issue a grant over a tier a subscription pays for without seeing the warning that the subscription keeps billing. Most of these reads leave no log line, so nothing records the fault behind the claim.
More operator pages show a failed read the same way:
internal/server/operator_billing.go) read each row's organization and Stripe mapping one row at a time. A failed organization read leaves the row without the organization's name, and a failed mapping read shows the row as not mapped. The customer lookup ininternal/server/operator.goloses a candidate's organization name the same way.internal/server/setup_state.go) skips a set whose rules cannot be read, so it can read complete when every rule read fails. The entitlement sets list (internal/server/operator_entitlement_sets.go) shows 0 rules for a set whose rules could not be read.internal/server/operator_billing.go) shows a price as not mapped when its mapping read fails.