v0.1.2 — fail closed on a corrupt stored DBSC record
Security / correctness
Fail closed on a corrupt stored DBSC record.
A stored binding (or pending-registration) record that was present but unparseable previously decoded to null, and the recommended host gate treats null as "no binding → degrade to cookie auth". A corrupt binding therefore silently downgraded a hard-DBSC session to plain cookie auth, re-opening the stolen-cookie hole DBSC exists to close. The docblocks claimed this "failed closed"; it did not.
Not client-triggerable. The write path always emits valid, well-typed JSON; the only client-derived field (publicKeyPem) is structurally validated first. The realistic trigger is an internal phpredis-serializer / truncation / cross-version-schema event. This is a defense-in-depth and contract-correctness fix.
Changes
- New
Exception\CorruptStateException(extendsDbscException). Binding::fromJson()/PendingRegistration::fromJson()now throwCorruptStateExceptioninstead of returningnull; return type?self→self.nullis reserved for "no record".StoreInterfacedocuments the absent-vs-corrupt contract explicitly.DbscServer::revoke()swallowsCorruptStateExceptionso a corrupt record is still deleted and audited rather than aborting teardown;@throws CorruptStateExceptionadded to the store-reading public methods.
Upgrading
Source/binary compatible for the recommended host wiring: CorruptStateException extends DbscException, so the gate read fails closed (uncaught → 500), the refresh terminal path's existing catch (… | DbscException) revokes + logs out, and register → 401. InMemoryStore is unchanged. If you call Binding::fromJson() / PendingRegistration::fromJson() directly, note they no longer return null — wrap in try/catch (CorruptStateException).
Full Changelog: v0.1.1...v0.1.2