PolyWood Price Builder

Rulesets and Assignments

Storage Layout

src/lib/s3-rulesets.ts stores JSON under configured prefix (RULESETS_S3_PREFIX, default rulesets) in RULESETS_S3_BUCKET (fallback PRODUCTS_S3_BUCKET):

  • <prefix>/<rulesetId>/meta.json
  • <prefix>/<rulesetId>/latest.json
  • <prefix>/<rulesetId>/versions/vNNNN.json
  • <prefix>/assignments/products.json

Ruleset Behavior

  • Ruleset IDs are required on create and strictly validated as [a-z0-9-]{2,64}.
  • POST /api/rulesets uses saveRulesetInS3:
    • if ruleset does not exist, create v0001
    • if ruleset exists, publish next vNNNN version
  • Rulesets are listed by scanning meta.json objects and sorted by updatedAt desc.
  • Each ruleset version document includes:
    • rulesetId
    • version
    • createdAt
    • steps
    • tierPolicy

Step Parsing and Validation

parseRuleStepsInput (API write path):

  • Requires an array of explicit widget steps: { id?, widgetId, config }.
  • Rejects unknown widget IDs.
  • Rejects unsupported config keys for the referenced widget.
  • Enforces field type/range constraints using current widget manifest definitions.

parseRuleStepsFromStorage (S3 read path):

  • Still requires explicit widgetId step shape.
  • Uses lenient config normalization:
    • known widgets get field-default/type/range normalization
    • unknown widgets are preserved with best-effort config pass-through

No legacy { type, op/value } conversion exists in current parser.

Tier Policy Integration

  • API input requires tierPolicy and validates it through parseTierPolicyInput.
  • Stored version JSON is parsed through parseTierPolicyFromStorage (fallback-tolerant read behavior).
  • listRulesetsFromS3 and getRulesetFromS3 return versions with resolved tierPolicy.
  • Detailed tier model and validation rules are documented in _docs/tier-pricing-policy.md.

Assignment Behavior

  • Assignment payload is an object keyed by SKU with { rulesetId, version }.
  • Input parser strictly validates rulesetId as [a-z0-9-]{2,64} and requires a non-empty version string.
  • API validation ensures assigned ruleset IDs exist before saving.
  • GET /api/rule-assignments returns { assignments, source }; if the S3 object is missing it returns assignments: {} with source.exists: false instead of failing.
  • UI currently writes version: "latest" when saving assignments.