Files
hanzo-dev e2311f80b6
CI/CD / containment (push) Successful in 2m27s
Hanzo CI/CD / cicd (push) Failing after 26m10s
CI/CD / gate (push) Failing after 26m25s
CI/CD / image (push) Skipped
CI/CD / rollout (push) Skipped
CI/CD / reach (push) Skipped
CI/CD / fanout (push) Skipped
CI/CD / receipt (push) Skipped
commerce's generated families state their own gate, because the seventeen do not share one
The 119 derived sentences were true about tenancy and silent about everything
else, and the seventeen families they cover are not uniform on the axis that
matters to a caller. Read off mount.go and commerce's api/resources:

  - transfer, wallet and webhook are ADMIN-gated (TokenRequired(permission.Admin)).
    A plain member's token is refused 403 there, on reads as much as writes.
  - collection, discount, product, variant, saleschannel and stocklocation sit
    behind paywall.Require: no active subscription, trial or redeemed invite is
    402 subscription_required, and an unreadable billing store fails closed 503.
  - collection, product, return, subscriber and variant additionally carry a
    DefaultPermissions table that CheckPermissions enforces per method (403).
    The other twelve have no table, and the miss logs and ALLOWS — so claiming a
    scope check on those would be prose the server does not honour.

One sentence repeated seventeen times said none of it, which is worse than the
bare operationId it replaced: it told a reader that a plain token may write a
wallet and that the only refusal on a product is 404. A description nothing
downstream can check is believed. So the table now carries the gate — the only
thing that actually varies — and the sentence is generated from it.

Three corrections to the shape prose while reading the handlers:

POST on the item address is the METHOD-OVERRIDE door, not "an address that
accepts every method". With no override it runs r.Patch; `_method` (form or
query) or X-HTTP-Method-Override set to PUT, PATCH or DELETE runs THAT one, so a
POST here can DELETE the record. An invalid override is ignored, not 405'd —
IsValidMethodOverride only admits those three and the method stays POST.

LIST returns the Pagination envelope {page, display, count, models, facets}, not
a bare array, and it fails closed to an EMPTY PAGE with 200 when no org
namespace resolves — so empty `models` does not mean "no records exist".

PUT decodes onto an empty record carrying only the existing key, which is why
omitted fields are reset; PATCH decodes over the loaded record. Both 404 on an
unknown id. DELETE writes a copy aside under an internal deleted key first, so
the row stops answering but is not erased.

Also: a family that outgrows the table comes OUT of it rather than gaining a
Describe as well — Describe panics on a duplicate key, so doing both aborts the
binary at init. The old comment said the explicit one "wins", which would have
sent the next reader into that panic.

Regenerated: openapi.yaml and plugin/commerce/openapi.json. 119 operations, none
bare; regenerating from source reproduces these bytes exactly.

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-08-05 18:04:20 -07:00
..
2026-08-05 01:42:27 -07:00