Repository navigation
PAY-001A — Add bounded request validation and safe logging primitives #157
Description
Officer impact: No current officer screen or procedure changes. This adds a reusable server safety layer so later race registration, merchandise, refund, and admin commands can reject malformed input before touching Firebase or Stripe.
Officer documentation: None — this atomic child is a pure server library with no public or officer-visible behavior. Later endpoint-wiring children must update the affected officer procedures.
Deployment evidence: None at issue creation. Closure proves source, tests, review, merge, and exact-commit CI only. No endpoint uses these helpers yet; no website, Firebase, Stripe, provider, or production behavior may be called deployed or verified.
Parent and dependencies
Atomic PAY-001A child of catalogued PAY-001 in GITHUB_ISSUES.md and GITHUB_ISSUE_SLICES.md.
- CI-001A/CI-001A — Repair the deterministic frontend test baseline #103 and its hosted frontend gate are merged.
- The ABUSE-001 deferred-callable boundary is documented.
- CONFIG-001A/CONFIG-001A — Require typed server environment, origin, and Stripe mode before side effects #149 and CONFIG-001B1/CONFIG-001B1 — Enforce server-only runtime commerce admission controls #151 are merged and must be preserved.
- PAY-003A — Harden Stripe webhook ingress and monotonic event reduction #101/PROMO-001 — Disable unmodeled Stripe price adjustments #102 own existing Stripe webhook and promotion behavior and are immutable here.
This child unlocks PAY-001B/C/D and PAY-002A. It does not wire any endpoint.
Problem
Current Functions validate inputs inconsistently. A future payment or admin command could accept arrays as objects, inherited/prototype fields, unexpected keys, excessive nesting, unsafe money, malformed dates or URLs, oversized text, or sensitive/high-cardinality logging fields.
Endpoint-by-endpoint fixes would drift. We need small pure CommonJS primitives with exhaustive hostile-input tests before those endpoints are migrated.
Atomic outcome
Add two dependency-free server libraries:
requestValidation: strict plain-object and own-property validation; unknown-key rejection; bounded depth/field/string/array helpers; safe nonnegative integer cents; explicit currency normalization; strict dates; HTTPS and explicitly allowed loopback URLs; bounded normalized email; fixed public-safe validation errors.safeLogging: build a new immutable structured-log projection from an explicit allowlist of low-cardinality fields and fixed safe values. Caller-supplied bodies, arbitrary keys, tokens, URLs, addresses, contact fields, Stripe/OAuth material, and raw errors are never copied.
Security invariants
- Reject
null, arrays-as-objects, class instances, symbol keys, accessors, inherited enumerable fields, and dangerous own keys such as__proto__,prototype, andconstructor. - Validation is deterministic, bounded, and has no Firebase, Stripe, network, clock, randomness, logging, or mutation side effect.
- Reject unsafe, fractional, negative, signed-string, exponent, boolean, NaN, Infinity, and over-limit monetary values.
- Currency is explicit and allowlisted; no locale guessing or floating-point conversion.
- Dates are strict canonical values with calendar round-trip checks; URLs are HTTPS except an explicit test/development loopback option.
- Email normalization is bounded and conservative; it is syntax validation, not account identity or deliverability proof.
- Public errors use fixed categories/messages and never include the supplied value, field contents, provider details, stack, or raw error.
- Structured logs are constructed from explicit safe fields; no recursive “redaction” of an unsafe object and no caller-selected log keys.
- Results are new immutable values. Input objects are never modified.
- Tests use hostile synthetic canaries only and make no external call.
Exact source boundary
- New
functions/requestValidation.js - New
functions/requestValidation.test.js - New
functions/safeLogging.js - New
functions/safeLogging.test.js - Minimum exact status/design hunks in:
STRIPE_COMMERCE_DESIGN.mdSECURITY.mdGITHUB_ISSUES.mdGITHUB_ISSUE_SLICES.mdIMPLEMENTATION_PLAN.md
Post a scope amendment before editing existing endpoints, stripeHelpers.js, serverConfig.js, commerceControl.js, package/lockfiles, Rules, client code, workflows, officer guides, providers, deployment configuration, or production data.
Acceptance criteria
- Strict-object tests reject arrays, instances, symbols, accessors, inherited fields, dangerous keys, and every unknown own key.
- Bound tests cover depth, total field count, arrays, strings, Unicode normalization/length, and hostile HTML without executing or logging it.
- Money tests cover zero/max, negative, fractional, unsafe, string/exponent, boolean, and invalid/unsupported currency values.
- Date, URL, and email tests cover canonical positives and malformed, oversized, encoded, credential-bearing, non-HTTPS, and loopback boundaries.
- Safe errors have fixed codes/messages and never echo a hostile canary or raw error.
- Safe log projections accept only documented low-cardinality fields and cannot emit bodies, arbitrary keys, tokens, URLs, addresses, email, phone, Stripe/OAuth values, or hostile canaries.
- Returned objects/arrays are frozen or otherwise immutable; inputs remain byte/deep equivalent and unfrozen.
- Tests deliberately fail if any external Firebase/Stripe/network/logger dependency is introduced or called.
- Node 20 focused tests, full Functions lint/tests, hosted CI, diff/sensitive-pattern review, and independent review pass.
- Root design/status docs say the primitives are merged only after merge and say endpoint adoption/deployment/live behavior remain NOT AVAILABLE YET.
Excluded
- Endpoint schemas or endpoint migration (PAY-001B/C/D).
- Payment/order/registration reducers or idempotency (PAY-002).
- Webhook behavior (PAY-003A — Harden Stripe webhook ingress and monotonic event reduction #101/PAY-003).
- Rate limits/App Check/abuse wiring, Firebase Rules, client validation, UI, provider configuration, dependencies, deployment, or production data.
Claim protocol
Creation is not a claim. Before editing: confirm the exact current-main SHA, assign the issue, post CLAIMED by /root at <UTC>; branch codex/issue-<number>-request-safety-primitives, apply status:in-progress, and use an isolated worktree. One atomic source/test outcome at a time.
Activity
daliu commentedon Jul 13, 2026
CLAIMED by /root at 2026-07-13T13:41:24Z; branch codex/issue-157-request-safety-primitives; exact base 594306f. Exact source boundary is the four new pure Functions library/test files plus minimum five root-document status/design hunks. Existing endpoints, packages, Rules, client, workflows, providers, deployment, and production data remain immutable.
daliu commentedon Jul 13, 2026
EXTRACTION FINISHED by /root at 2026-07-13T14:24:50Z.
codex/issue-157-request-safety-primitives594306fb06d9a6a2a44b5675b305f462f11b877d508145eaefc972fd6bcc0b2778961c3091f0a032Next state is commit and pull-request review. PAY-001B/C/D, endpoint schemas, nested exact schemas, immutable snapshots, deployment, and live protection remain open.
daliu commentedon Jul 13, 2026
COMPLETED by /root at 2026-07-13T14:32:43Z.
e5a0390f8c1c9dc9a51f83457cd3623ea0bc9723.e5a0390f.