Skip to content

SimSwapAgeBand schema can't express valid limits for the 111 sentinel (S-310/S-311 in #276) #277

Description

@hdamker

Thanks to everyone who worked through #253/#260/#266/#273 — that was a long, careful thread and the resulting /retrieve-age-band endpoint is a genuinely useful addition. I don't have maintainer standing on this repo, and #273 is already merged — please treat this as a follow-up flag rather than a blocking objection; fine to close as won't-fix if the group prefers to leave it as-is.

Problem description

SimSwapAgeBand (added in #273) is type: integer with enum: [1, 2, ..., 17, 111], where 111 is a sentinel ("provider positively confirms a SIM swap has never happened for the subscriber and the number has never been ported") that deliberately sits far outside the 117 ordinal range.

Per the API Design Guide §2.2, an integer field MUST specify format and a minimum/maximum range — there's no enum-based exception for integers (unlike strings, where enum substitutes for maxLength). That's what's driving the S-310/S-311 findings already tracked in #276.

This isn't just a missing annotation — there isn't a correct minimum/maximum pair for this domain. 117 is a genuine, ordered range; 111 is explicitly documented as "NOT a position in the recency sequence." Any single numeric range either has to include 111 (misleadingly implying 18110 are valid, or that 111 is "past band 17") or exclude it (contradicting the schema's own enum). Adding numbers to satisfy the linter won't fix this — the value domain genuinely can't be described by one min/max pair.

Possible evolution

Re-type the field as a string enum, which sidesteps the range problem since enum alone satisfies §2.2 for strings — e.g. BAND_01...BAND_17 plus a NEVER_SWAPPED value for the sentinel. Zero-padding the rank into the value (rather than a duration mnemonic like WITHIN_4H) keeps today's threshold comparisons working: plain string comparison ("BAND_03" <= "BAND_09") reproduces the same ordering as the current 3 <= 9, so consumers doing band-edge checks (e.g. the 72h/96h split from #273) don't need a lookup table or a unit-aware parser.

Alternative solution

No strong stake in that specific shape — happy to sketch it out further if useful, or to leave the fix entirely to the group for whenever this operation is next touched.

Additional context

  • Out of curiosity: the enum went through a few shapes across #260/#266/#273-1/0/115 in #260 and #266's initial version, then 115 + 999 in #273's first draft, settling on 117 + 111 after review. The -1/0 scheme at least kept the sentinels adjacent to the real range; unclear from the thread what motivated the move to a value chosen specifically to sit far outside it instead. Not trying to relitigate that — just flagging in case it's relevant to how you want to resolve this.
  • sim-swap is still alpha in the current release plan, so this should still be cheap to adjust if the group agrees it's worth doing before rc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions