Skip to content

refactor: fail closed on stored shapes the server doesn't write and start versions at their first released value - #545

Merged
polewskm merged 12 commits into
mainfrom
claude/drop-prerelease-readers
Nov 3, 2026
Merged

polewskm merged 12 commits into
mainfrom
claude/drop-prerelease-readers

Conversation

@polewskm

@polewskm polewskm commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Nothing reads a stored shape the serving code doesn't write, and no identifier or version is held for an unreleased state. That follows the project owner's standing direction: nothing is shipped, so there is no earlier data to keep readable.

  • A stored record that lacks what the serving code writes is malformed and fails closed (ADR-1395).``
    • A grant payload that isn't a $ver/$payload envelope is rejected with a JsonException. The envelope and upcaster seam stay for use after the first release.
    • A session grant carries required IdleTimeout and AbsoluteExpiresWhen, written with its payload. DefaultSessionService refuses to serve a session grant without an expiration.
    • A tenant without an issuer is malformed and fails closed.
  • Identifiers and versions start at their first released value (ADR-1397).```
    • The audit record's schema_version is 1.0, which includes tenant_environment_type. Adding a field bumps the minor version.
    • The log event ID lists hold assigned IDs only, with nothing reserved.

ADR-1395 overrides project-template ADR-0108's rule that a document without $ver is read as version 1; #542 proposes the matching template change. #535 carries the release-time step: from then on, a grant payload evolves through a version bump and an upcaster, and a shipped event ID is never reused.

…oes not write

A grant payload that is not a schema-versioned envelope is rejected with a
JsonException. SessionGrant.IdleTimeout and SessionGrant.AbsoluteExpiresWhen
are required, so a session ends at its own absolute end or idle window, and
the ended-session pass selects only grants whose expiry has passed.

ADR-1395 records the decision, amends ADR-1113, ADR-1220 and ADR-1223, and
overrides project-template ADR-0108's reading of a document without $ver.
…d values

The audit record's schema_version is "1.0", and the 1.0 record carries
tenant_environment_type. EventIds.cs carries no reservation for an event ID
that no release used, so a later event may take it; the append-only rule
protects shipped IDs.

ADR-1397 records the decision and amends ADR-1167, ADR-1246, ADR-1283 and
ADR-1289.
The persisted-payload rule states the rule in force first: a stored
document that lacks what the serving code writes fails closed, a payload's
shape changes in place until the first stable release, and the released
shape evolves additively from then.

A session grant without an expiration is malformed: reading it throws an
InvalidOperationException, as a session payload without its bounds throws a
JsonException. ADR-1395 names the requests that fail on a malformed session,
the session listings among them, which do not skip it.

The audit schema's minor-version rule applies to a released schema, and
ADR-1397 lists the event IDs the records held, in the present tense.
…e-readers

# Conflicts:
#	CHANGELOG.md
#	docs/conformance/external-suite.md
#	docs/conformance/login-consent-ui.md
#	src/NCode.Identity.Events/Logging/EventIds.cs
#	src/NCode.Identity.OpenId.Authentication/Endpoints/BackchannelAuthentication/Delivery/CibaDeliveryJobHandler.cs
#	src/NCode.Identity.OpenId.Authentication/Logging/EventIds.cs
#	src/NCode.Identity.OpenId.Authentication/Sessions/BackChannelLogoutDeliveryJobHandler.cs
#	src/NCode.Identity.OpenId.Core/Settings/DefaultSettingDescriptorDataSource.cs
#	src/NCode.Identity.OpenId.Core/Tenants/DefaultOpenIdTenantFactory.cs

@ncode-review ncode-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 NCode Review at 38e2b73: 2 new findings on the changed lines.

Not on a changed line:

  • 🟡 F2 Nit: Amended ADR bodies still contradict their new status lines docs/decisions/1283-audit-records-are-cloudtrail-shaped-json-with-an-indexable-envelope.md:105. ADR-1283 decision 13 still says 14003 and 14004 are reserved and never reused, while its status line says they are free. ADR-1220 (around line 57) still describes a session stored without an absolute end. Fix: If the convention is to update the body as well as the amendment line, edit ADR-1283 decision 13 and the ADR-1220 text so they match.

@ncode-review

ncode-review Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Superseded by the review at 68654f1.

@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #545      +/-   ##
==========================================
- Coverage   92.18%   85.49%   -6.69%     
==========================================
  Files        1513     1495      -18     
  Lines       63624    61985    -1639     
  Branches      306      707     +401     
==========================================
- Hits        58649    52992    -5657     
- Misses       4975     8993    +4018     
Flag Coverage Δ
dotnet 84.83% <100.00%> (-7.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

📢 Thoughts on this report? Let us know!

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

polewskm commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Autopilot: F2 (not on a changed line, no change): ADR-1283 decision 13 and the ADR-1220 text are the bodies of accepted records. The repository updates an accepted record through its status, not its body: docs/decisions/README.md says a new record "supersedes the old one (and update the old one's status) rather than editing history", and ADR-1393 decision 5 makes the Status, Amends and Supersedes lines the mechanism. ADR-1283's and ADR-1220's status lines name ADR-1397 and ADR-1395, and those records state the decisions that hold: the log event IDs list assigned IDs only, and a session grant has required bounds.


Generated by Claude Code

@polewskm

polewskm commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

/review

@ncode-review

ncode-review Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

🤖 Review complete

Verdict: ✅ Approve — Deep review (sensitive paths): Re-review of what changed since the last review at 38e2b73: 29 hunks in 8 files and changes taken back in 3 files, by correctness and security. No further findings above nits.

2 reviewers run — 0 findings (run details)

Reviewer Model Findings Top
correctness opus-5-5 0 🟢
security opus-5-5 0 🟢

Trial: findings are posted as review threads and in the check run. $0.31 on Amazon Bedrock, 23s, at 68654f1. (how to interact)

📋 Outcomes

Merged at a09410a: 2 fixed, 0 dismissed, 0 acknowledged, 0 ignored.

Finding Reviewer Severity Outcome
F1 correctness 🟠 Should fix ✅ fixed
F3 rule-check 🟡 Nit ✅ fixed

@polewskm
polewskm marked this pull request as ready for review November 3, 2026 14:31
@polewskm
polewskm deployed to code-review November 3, 2026 14:31 — with GitHub Actions Active
@polewskm
polewskm added this pull request to the merge queue Nov 3, 2026

polewskm commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Autopilot: Ready to merge. NCode Review approves 68654f1 with no findings, every review thread has a reply, and CI is green. It touches the same changelog and decision-index area as #544, so if one lands first and the other conflicts, I'll merge main into the second and push the resolution.


Generated by Claude Code

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 3, 2026
@polewskm
polewskm enabled auto-merge November 3, 2026 15:04
…e-readers

# Conflicts:
#	src/NCode.Identity.OpenId.Authentication/Logging/EventIds.cs
…e-readers

# Conflicts:
#	docs/decisions/1220-an-end-user-session-always-ends-and-its-grant-expires-when-it-does.md
#	docs/decisions/1223-a-session-that-ends-unused-is-terminated-once-in-the-background.md
#	docs/decisions/README.md

polewskm commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

Autopilot: merged main (#531, #543 and #544) and resolved the conflicts.

./build/dod.ps1 -Fast -Affected passed after the #531 merge. The #544 merge conflicted only in documentation, so it was pushed without re-running the gate. This is safe to re-queue once CI is green.


Generated by Claude Code

@polewskm
polewskm added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit 988d7b8 Nov 3, 2026
15 checks passed
@polewskm
polewskm deleted the claude/drop-prerelease-readers branch November 3, 2026 16:42
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