S18 — Members-only rule guard (a check before payment)
When the cashier presses Pay, the shop's server prices the basket and asks this service. It refuses a sale that holds a members-only item for a customer who is not a member, in its own words, and asks the cashier for ID when the sale is at or above the shop's limit. Everything else is allowed. A refused sale books nothing.
The recipe: recipes/rule_guard.md.
| File | What it is |
|---|---|
manifest.json |
one check service, installed switched off, refuse when the service is down |
rule.py |
the pure core: the signature check (verify), the shape check (context_of), the rule (decide) |
service/app.py |
the service, standard library only: POST /rgd/check, GET /health |
tests/ |
the rule, the service over the wire with signed calls, every answer against the published contract |
Settings (service/.env.local, never committed): PP_POINT_SECRET (handed back at install as pp_rgd:sub:guard), PP_PORT, PP_MEMBERS_ONLY_ITEMS and PP_MEMBERS_ONLY_GROUPS (comma lists), PP_MEMBER_GROUPS (the shop's member customer groups), PP_ASK_ABOVE (the ID limit in whole currency units; blank = never ask).
python3 service/app.py service/.env.local
python3 -m unittest discover -s samples/s18_rule_guard/tests -p 'test_*.py'
The service reads nothing from the shop and writes nothing: the till sends the priced basket, the service answers. Returns are never guarded by this rule.