Skip to content

Enums never take a String raw value; CredentialRejectedError redesign; one typed error envelope; FOSTesting depth; review project-scope clauses - #144

Merged
foscomputerservices merged 7 commits into
mainfrom
feat/no-string-backed-enums
Sep 3, 2026
Merged

Enums never take a String raw value; CredentialRejectedError redesign; one typed error envelope; FOSTesting depth; review project-scope clauses#144
foscomputerservices merged 7 commits into
mainfrom
feat/no-string-backed-enums

Conversation

@foscomputerservices

Copy link
Copy Markdown
Owner

Summary

Seven commits, one arc: the first full customer review run and the review of one of our own types.

fosmvvm-review evaluates project-scope clauses once. A large area is partitioned by module explicitly, and the clauses that answer a question about the whole project ("no behavioral suite exists", "no committed .VersionedTestJSON", "the boot path never installs the error middleware") carry **Scope:** project and run in exactly one partition; the aggregator collapses any duplicate. Plugin 2.65.0.

Enums never take a String raw value. Truth statement in the architecture doc; no-string-backed-enums (cross-cutting, blocker; tools, not libraries, are exempt); LocalizableString.localized(case:parentType:) derives the YAML key from the case; the serverrequest, fields, and viewmodel generators and both DocC articles teach the plain-enum form. The framework's five FOSMVVM enums drop their raw values; FormInputType and FormInputOption.Autocomplete keep their HTML tokens as htmlAttributeValue. Plugin 2.66.0.

CredentialRejectedError is plain data. reason (Reason.missing / .invalid) and a typed CredentialChallenge (.bearer, .bearerRealm(_:), .basicRealm(_:)) with synthesized Codable; the hand-rolled discriminator envelope is gone. Every ServerRequest error body now crosses the wire inside one typed envelope encoded by FOSMVVMVapor.ErrorMiddleware and decoded by the client and the FOSTestingVapor harness — no trial decode. The rejection no longer conforms to AbortError: the middleware assigns its 401 and WWW-Authenticate (the error token follows the reason, RFC 6750 §3.1). The stale DocC that taught hand-rolled retry is rewritten around the refresh seam. Wire contract: a client and server on either side of this release see each other's error bodies as undecodable and fall to the status path; upgrade both together.

FOSTesting depth. expectFullViewModelTests(_:locales:version:); expectTranslations walks child ViewModels, optionals, and collections and names the failing path; the test encoder is strict (LocalizerError.missingTranslation), production encoding unchanged; setUp(bundles:) fails loudly when the bundles yield no YAML (bundles: [] opts into key-echo).

Ledger. Three framework gaps recorded in docs/deferrals.md (non-Fluent write door, socket-channel door, raw-bytes transfer) and one deferral (the rejection's localized message waits on a framework YAML bundle).

Verification

  • Full package green: FOSMVVM 467 (four new: translation walk, strict encoder), Vapor suites 254 + 463 (envelope round-trips, dressing through the middleware, custom verifier), bootstrap 90, foundation 63.
  • swiftformat and swiftlint clean on every changed Swift file.
  • Diff audited for customer names: none on any added line.

Ships as 0.16.0 (public API added; wire contract changed).

…partitions

Step 5 names the partition rule for large areas (by module, about 100
files per dispatch) and the project-scope dispatch; checks whose clauses
answer a question about the whole project carry a Scope: project mark
(behavioral-suite-standing clause 1, versioned-baseline-committed,
server-installs-the-error-middleware) and run in exactly one partition;
Step 6 collapses duplicates across partitions. Plugin 2.65.0.
…rentType:); no-string-backed-enums check

The truth statement lands in FOSMVVMArchitecture.md and its Simple Errors
section teaches the plain-enum form. LocalizableString gains
localized(case:parentType:), which derives the YAML key from the case.
fosmvvm-review gains no-string-backed-enums (cross-cutting, blocker); the
serverrequest, fields, and viewmodel generators, the serverrequest check's
example, and both DocC articles teach the plain form. The framework's five
String-backed FOSMVVM enums drop their raw values; FormInputType and
FormInputOption.Autocomplete keep their HTML tokens as htmlAttributeValue,
derived on the owner. Plugin 2.66.0.
…enge; one typed error envelope on the wire

CredentialRejectedError carries reason (Reason.missing/.invalid) and a
typed CredentialChallenge (.bearer, .bearerRealm, .basicRealm) with
synthesized Codable; the hand-rolled discriminator envelope is gone. Every
ServerRequest error body now crosses the wire inside the WireError envelope,
encoded by FOSMVVMVapor.ErrorMiddleware and decoded by the client and the
FOSTestingVapor harness, so the client never trial-decodes a body. The
rejection no longer conforms to AbortError: ErrorMiddleware assigns its 401
and WWW-Authenticate (the error token follows the reason per RFC 6750). The
stale DocC that taught hand-rolled retry is rewritten around the refresh
seam.
…ons walks child ViewModels; strict test encoder; loud empty UI-test harness

expectFullViewModelTests forwards a version: to the version-stability check.
expectTranslations descends into stored child ViewModels, optionals, and
collections and names the failing path. LocalizableTestCase's encoder is
strict: a key the store cannot resolve fails the encode with
LocalizerError.missingTranslation (JSONEncoder.localizingEncoder gains the
strictLocalization switch; production encoding is unchanged).
ViewModelViewTestCase.setUp(bundles:) throws RunError.noLocalizationYAML when
the given bundles yield no YAML; bundles: [] opts into key-echo explicitly.
@foscomputerservices
foscomputerservices merged commit f20da20 into main Sep 3, 2026
20 checks passed
@foscomputerservices
foscomputerservices deleted the feat/no-string-backed-enums branch September 3, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant