Hidden Assumptions in spree

12 assumptions this code never checks · 4 critical · spanning Contract, Environment, Ordering, Resource, Temporal, Scale, Shape, Domain

Every codebase relies on things it never checks. Most of them are routine. CodeSea looked at spree/spree and picked out the few most likely to cause trouble. The full list is just below.

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

When Ruby serializers evolve (add required fields, change types, rename properties), existing TypeScript client code silently receives malformed data or fails at runtime with no compile-time warning

Worth your attention first

Invalid ports (like 'abc' or '99999') cause Docker services to fail to start with cryptic errors, while used ports cause silent conflicts where CLI commands target wrong services

Worth your attention first

If backend template changes service names or structure, generated projects have broken Docker configurations and CLI commands fail with 'service not found' errors

Show everything (9 more)
Resource

GitHub backend template repository is accessible and contains expected directory structure with docker-compose.yml in root — no rate limiting, authentication, or repository structure changes

If this fails: Network failures or GitHub API limits cause scaffold process to hang or fail partway through, leaving incomplete projects that appear valid but miss critical backend components

packages/create-spree-app/src/scaffold.ts:downloadBackend
Temporal

Spree backend health endpoint (/health) becomes available within reasonable time (implied max ~6 minutes based on 3-second intervals) and responds with expected format

If this fails: If backend takes longer to initialize or health endpoint changes format, CLI hangs indefinitely or proceeds with unready services, causing database seeding and other operations to fail mysteriously

packages/cli/src/commands/init.ts:health check polling
Scale

HTTP retry logic with exponential backoff (3 attempts max) is sufficient for all network conditions, and that 5xx errors are always transient and worth retrying

If this fails: During high load or persistent server issues, requests fail after only 3 attempts even when longer retry sequences would succeed, while persistent 503s from overloaded servers waste resources on futile retries

packages/sdk-core/src/request.ts:createRequestFn
Shape

Backend always returns checkout validation errors in exactly 3 fields (step, field, message) with string types, and that step names are consistent across different checkout flows

If this fails: If backend adds metadata fields or changes step naming conventions, checkout validation becomes unreliable and storefront displays malformed error messages to users

packages/sdk/src/types/index.ts:CheckoutRequirement
Domain

Generated SECRET_KEY_BASE values have sufficient entropy for production security and that Ruby on Rails secret generation requirements don't change

If this fails: If entropy is insufficient or Rails changes secret format requirements, generated projects have weak session security or fail to start with cryptic Rails errors

packages/create-spree-app/src/templates/env.ts:generateSecretKeyBase
Contract

MDX components follow consistent naming patterns (Info/Warning/Tip) and self-closing syntax, with no nested JSX or dynamic attributes that would break regex-based conversion

If this fails: Complex MDX content with nested components or attributes gets mangled during conversion, producing broken documentation with missing or malformed sections

packages/docs/scripts/convert.js:convertContent
Ordering

Command registration order doesn't affect functionality and all commands can be safely registered in any sequence without dependencies between them

If this fails: If commands have hidden dependencies (like 'init' must run before 'seed'), the registration order might mask these dependencies until runtime conflicts occur

packages/cli/src/index.ts:command registration
Environment

Package manager detection correctly identifies npm/yarn/pnpm from environment, and that detected package manager has compatible command interfaces for dependency installation

If this fails: Wrong package manager detection leads to failed dependency installations during project scaffolding, while version incompatibilities cause cryptic error messages during setup

packages/create-spree-app/src/index.ts:detectPackageManager
Temporal

Typelizer digest hash changes only when actual type structures change, not when comments or non-semantic content changes in Ruby serializers

If this fails: False positive regeneration wastes build time and creates noisy commits, while false negatives leave stale types that diverge from backend reality without detection

packages/sdk/src/types/generated/index.ts:Typelizer digest

See the full structural analysis of spree: the pipeline, data models, and system behavior that put these assumptions in context.

Full analysis of spree/spree →

Frequently Asked Questions

What does spree assume that could break in production?

The one most likely to cause trouble: Generated TypeScript types from Ruby serializers maintain structural compatibility across versions — no field renames, type changes, or required field additions without coordinated updates If this fails, When Ruby serializers evolve (add required fields, change types, rename properties), existing TypeScript client code silently receives malformed data or fails at runtime with no compile-time warning

How many hidden assumptions does spree have?

CodeSea found 12 assumptions spree relies on but never validates, 4 of them critical, spanning Contract, Environment, Ordering, Resource, Temporal, Scale, Shape, Domain. Most are routine — the analysis flags the two or three most likely to actually bite.

What is a hidden assumption?

Something the code depends on but never checks: a data shape, an ordering, an environment condition, a scale limit, or a contract with another service. It holds until the world it runs in changes, then fails silently.