Repository navigation
Commit 93a6ba4
<!-- claude-projects-attribution: {"github_login":"os-sales"} -->
_Requested by **Sales** · [project
thread](https://claude.ai/code/project/chan_01D5bWFY3rFzgJcytD5gD4Uu?thread=cmsg_01D5bWFY3rFzgJcytD5gD4UuMjbPDrsigsyqoKsV4WZQMz)_
Part of #25224
Clause-②: no
Metadata-protocol: none
Ruling-ref: 6348891160, 6364006498
The basis for the `Clause-②: no` line: this is a move. No accept set,
route, refusal, code or answer changes, and the published surface is
measured unchanged:
- `@objectstack/plugin-auth`'s `dist/index.d.ts` and `dist/index.d.mts`
are raw byte-identical to base (0 diff lines, so the union-order
normalisation has nothing to do). The positive control is the one ruling
`6348891160` asks for.
- Its ESM and CJS entries export the same 159 names at base and at head.
The `.d.ts` bar is ruling `6348891160` item 1 (on #25222, covering this
card). Ruling `6364006498` is Sales's ruling A on this card. This is the
fourth cut it applies to.
Cut 12 of the `auth-manager.ts` split: **the global after-hook of the
better-auth instance**. It is the first of the three
`createAuthInstance` slices the seat set (`hooks.after`, then
`hooks.before`, then the rest of the method). #25224 stays open for the
later cuts.
This follows the amended claim `6374301142`, which amends `6372234293`
on the file cut 11 left (#25524, landed note `6373433471`). The shape is
cuts 1 to 11's, which is #23050's, applied to a closure instead of a
method. The seat ruled that in scope at 19:56Z, the same call as
#25223's `start()` R3, with the bars listed below.
Branch: `claude/project-thread-lg3wrj`, the harness-pinned branch for
this session, restarted from `origin/main` `1ff43b67ea` after #25524
merged. It names no issue, so the card relation is this body's first
line.
`auth-manager.ts` goes from 8,536 to 8,362 lines. The cut is +274 / −193
over 2 files: 467 changed lines, under the 3,000-line line. It is not a
governed surface (`check-governed-merges.mjs --branch HEAD`: NOT
governed). One commit: `d79f55f402` `refactor(plugin-auth): move the
better-auth global after-hook into auth-manager-after-hook.ts`.
## The move
| moved | base lines | proof lines | tokens | members it reads |
|---|---|---:|---:|---:|
| the `hooks.after` arrow body in `createAuthInstance` | `:2834`–`:3016`
| 185 | 610 | 8 methods |
The lines are base `1ff43b67ea`. The 185 proof lines are the body with
its braces (`:2833`'s `{` to `:3017`'s `}`).
- **What it is:** `createAuthInstance` (`:1699`, private, annotated
`Promise<Auth<any>>`) builds one config literal for better-auth. Its
`hooks.after` is `createAuthMiddleware(async (ctx: any) => {BODY})`: the
after-hook every better-auth endpoint's response passes through.
- **What BODY does, in order** (all of it moves, with its comments): the
bearer rotation on impersonation, the echo of the installed session
token, the session envelope completion, the two-factor re-enrolment
reset, the sign-in outcome count with the refusal audit, the
concurrent-session cap and the login stamp, the password-change stamp
and history commit, the old-address notice on an e-mail change, the
directory doors narrowed for an external caller, the invite-role refusal
code, and the sign-up `disableSignUp` restore.
- **Where it goes:** a new module,
`packages/plugins/plugin-auth/src/auth-manager-after-hook.ts` (255
lines). BODY becomes the body of `export async function
globalAfterHook(this: AfterHookHost, ctx: any)`, re-indented eight
spaces (four levels) and otherwise unedited. The module header gives the
reasoning, in the form the eleven earlier `auth-manager-*.ts` modules
use.
- **What stays:** `createAuthInstance` keeps its place, docblock and
signature, and `hooks.after` keeps its place in the literal. Its arrow
is now:
```ts
// [#25224 cut 12] The body moved to `auth-manager-after-hook.ts`; this
// arrow hands it the members it reads (`AfterHookHost`).
after: createAuthMiddleware((ctx: any) => {
const host: AfterHookHost = {
auditRefusedSignIn: (...a) => this.auditRefusedSignIn(...a),
// … one closure per member, alphabetical, 8 in all
};
return globalAfterHook.call(host, ctx);
}),
```
Nothing else in `createAuthInstance` changes.
## The seat's bars
**Body.**
- BODY is the same TypeScript token sequence at base and in
`globalAfterHook`: 185 lines, 610 tokens. Every line is the base line
minus exactly eight spaces, and the parameter list (`ctx: any`) is the
same text. Neither side has a return annotation.
- **`async` moves from the arrow to the function.** The head arrow is
not `async`, and it returns `globalAfterHook.call(host, ctx)`, the
function's own promise, unchanged. better-auth 1.7.12's
`createAuthMiddleware` is better-call 1.4.4's `createMiddleware`, whose
handler wrapper runs `const response = await _handler(internalContext);`
inside its `try` (`dist/middleware.mjs:15`). So it awaits the same
promise BODY settles, with the same value or rejection, and its `catch`
sees the same error. The host literal and the `.call` cannot throw
before that promise exists.
- **No captured locals.** None of the locals `createAuthInstance`
declares before the literal (`betterAuth`, `createAuthMiddleware`,
`setShouldSkipSessionRefresh`, `plugins`, `passwordHasher`) is read in
BODY. The binding proof below finds no identifier in BODY bound anywhere
else in the method either.
- **No `arguments`, `new.target` or `super`** (0 of each), where an
arrow and a function differ. There is no bare `this`: BODY's only `this`
uses are 9 member reads, `this.X`.
**Receiver.**
- BODY's `this` was the `AuthManager` instance, the arrow's lexical
receiver. It is now the host.
- `AfterHookHost` names exactly the 8 members BODY reads, no more, each
typed as the class member (`AuthManager['x']`): `auditRefusedSignIn`,
`enforceConcurrentCap`, `externalDirectoryDoorDeps`,
`recordPasswordHistory`, `recordSignInOutcome`, `sendChangeEmailNotice`,
`stampLastLogin` and `stampPasswordChangedAt`.
- All 8 are methods, so each goes as a late-bound closure, `(...a) =>
this.x(...a)`. The method runs on the manager and is looked up when BODY
calls it, so a spy or double set on the manager is still the one BODY
reaches.
- BODY reads no field, so there is no getter. No member BODY reads is a
function-valued field, so there is nothing to disclose the way #25516
disclosed `resolveKernelService`.
**Host lifetime.** The host is built inside the arrow, once per run of
the hook: each time better-auth runs `hooks.after` on an endpoint's
response. The seat allowed once per `createAuthInstance` call; this is
more often, and it is what every method stub in this series does.
Nothing BODY reads is captured early, because each closure looks its
method up on the manager at call time.
**Readers.** The decision letters are read at both ends below: 4 drop,
as expected. No anchor entry is owed. Tenant census and symbol-anchor
output are byte-identical at both ends, and the full plugin-auth suite
passes at both ends.
## Imports and evaluation order
Seven import lines leave `auth-manager.ts`, because BODY was their last
reader there:
- `narrowDirectoryForExternalCaller` (the line stays as `import { type
ExternalDirectoryDoorDeps } from './external-directory-door.js'`);
- `rotateCallerBearerOnImpersonation` (a three-line import block),
`echoInstalledSessionToken`, `resetVerifiedOnTwoFactorReenrollment`,
`codeInviteRoleNotFound`, `attachSessionToCredentialResponse` and
`readRequestClientAddress`.
`SIGN_IN_EMAIL_PATH` has other readers in `auth-manager.ts`, so both
files import it. One import line is added after cut 11's, with a comment
in the same form: `import { globalAfterHook, type AfterHookHost } from
'./auth-manager-after-hook.js'`. The new module imports the
`AuthManager` type only.
esbuild drops a type-only import, so a module whose last value import
leaves `auth-manager.ts` is now first evaluated later, when the new
module is reached. I read each top level:
- `two-factor-rotated-token-echo`,
`two-factor-reenrollment-verified-reset`, `invite-role-not-found-code`,
`session-envelope-completion` and `external-directory-door` are now
reached only through the new module. None of the five imports anything.
Their top levels are literals, interfaces and function declarations
(plus two arrow consts in `external-directory-door`), so there is no
side effect to reorder.
- `impersonation-bearer-rotation` is still reached earlier, through
`admin-impersonate-endpoint.ts:137`.
- `request-client-address` is now first reached through
`auth-manager-request-routing.ts`, before the new module. Its top level
is one `defineRequestState(() => undefined)` from
`@better-auth/core/context`, which creates a frozen ref object over the
per-request store and registers nothing globally, so the order cannot be
observed.
- The new module's own top level is imports, one interface and one
function declaration. Its import of `auth-manager.ts` is type-only, so
there is no runtime cycle.
## The decision-letter layer: −4, as expected
`check-adr-anchors`, measured at both ends. The gate exits 0 at both.
| point | anchored files | citations | files | decision letters |
|---|---:|---:|---:|---:|
| base `1ff43b67ea` | 83 | 52,270 | 6,675 | 1,971 |
| head `d79f55f402` | 83 | 52,270 | 6,676 | 1,967 |
- The four letters are in BODY's comments: ADR-0069 D2 (`:2882`, the
account lockout counter), D7 (`:2904`, the login audit stamp) and D1
twice (`:2918` and `:2995`, the password-changed stamps). They leave
`auth-manager.ts`, which is anchored, for a module that is not. Their
citations still resolve, so the citation count does not move.
- **No entry is owed.** The `auth-manager.ts` entry has two paragraphs:
ADR-0108 (better-auth's organization roles map) and ADR-0093 D2
(`settleMembership` and its two seams, `user.create.after` and
`session.create.before`). Neither describes `hooks.after`, and no other
entry names it. So, per the seat's bar, no entry is added for the new
module.
## Path readers
No path reader needs migrating: none reads a moved line.
- **The tenant-audit census.** No census site moves: BODY has no engine
write, no `this.X.delete()` and no elevation read.
`check-tenant-audit-census` exits 0 at both with no `--write`, and its
output is byte-identical. The `--json` document has 238 sites at both
and 0 per-site differences with line numbers ignored. 2 sites are in
`auth-manager.ts` at both (each 174 lines earlier at head, the cut's
net), and 0 are in the new module. Only `scannedSources` (743 → 744) and
`measuredAt` differ, so neither census document is edited.
- **`check-dispatcher-error-vocabulary.mjs`** and
**`api-error-code.pin.test.ts`'s `authManagerFiles` floor**: BODY has no
`new APIError(`. The gate reads 56 sites found and 56 classified at
both; only its scanned-file count moves (3,420 → 3,421).
- **`check-auth-mount-ledger.mjs`**: no base-path literal or declaration
is in BODY.
- **The plugin-factory scans** in `better-auth-schema-parity.test.ts`
and `managed-extension-fields.test.ts` match `better-auth/plugins…` and
`@better-auth/…` dynamic imports. BODY has no dynamic import, and both
suites pass at head.
- **`rate-limit-storage-isolation.test.ts`** walks the import graph from
`rate-limit-storage.ts`, which reaches neither file. It passes at head.
- **The system-context census** reads 149 elevation read sites at both,
with byte-identical output.
- **Every symbol anchor into the file.** Before the cut, every
`auth-manager.ts#symbol` anchor in the tracked tree outside changelogs
was mapped with `symbolSegmentResolution` from
`scripts/symbol-anchors.mjs`. There are 29, and all 29 are
`declaration`-class at base, at base with BODY blanked, and at head.
None of their symbols occurs as a token on a line of BODY.
## Proof
Builds and suites ran through `os-verify-lock`, and every exit code was
captured before any pipe. Base `1ff43b67ea`. A full `turbo run build`
ran first. Then `plugin-auth` was built and its suite run at base, and
built and run again at head, on the same dependency dists.
**1. The moved text.**
- **Token identity:** the base arrow body and the module function body
are the same TypeScript token sequence (scanner tokens, kind and text,
trivia skipped, each template literal re-scanned at its substitutions as
the parser does): 185 lines and 610 tokens, each line the base line
minus eight spaces.
- **The head arrow's shape**, checked by the same run: not `async`, the
same parameters, one host literal whose keys are exactly
`AfterHookHost`'s and whose every value is `(...a) => this.<key>(...a)`,
then `return globalAfterHook.call(host, ctx)`, and nothing else.
- **Binding identity:** a second proof walks all 181 identifiers of BODY
at base and in the module, in order, and resolves each with the
TypeScript checker. All 181 resolve the same way at both ends:
- 38 to the `ctx` parameter;
- 56 to a declaration inside BODY, the same declaring identifier by
position;
- 9 to the receiver's members (`AuthManager` at base, `AfterHookHost` at
head);
- 8 to imports with the same specifier and imported name;
- 70 to no declaration: the globals `Error` and `undefined`, and
property names on untyped values.
None resolves to a `createAuthInstance` local or to a top-level
declaration of either file.
- **Negative controls:** both proofs read the module text, and each
control changes it in memory only; the file is untouched.
- Token proof: `await rotateCallerBearerOnImpersonation(ctx);` changed
to `void …` fails the token and line checks, and the run exits 1.
- Binding proof: the module's `readRequestClientAddress` import pointed
at another specifier gives 1 difference, and the run exits 1.
- **An independent reading:** `git diff --color-moved=plain
--color-moved-ws=allow-indentation-change 1ff43b6 d79f55f` over
the source files marks 188 of the 193 deleted lines and 194 of the 274
added lines as moved.
- The 5 unmoved deletions are the `external-directory-door` import line
(now type-only), the three-line `rotateCallerBearerOnImpersonation`
import block (now one line in the module), and the `after:
createAuthMiddleware(async (ctx: any) => {` line (now without `async`).
- The other added lines are the module header, the host interface and
its docblock, the function signature, the arrow's host literal and
`return`, and the two new import comments and lines.
**2. `.d.ts` and exports (ruling `6348891160` items 1 and 2).**
| file | base and head | raw diff lines |
|---|---|---:|
| `dist/index.d.ts` raw |
`1b3a48357d137155de33104277667a922aab62df73b418b03894c56faaacd0ba` | 0 |
| `dist/index.d.ts` normalised |
`cee7303ccdfe72794efd588c85b628419d4253d730b5a0c5a3f1cdb8dddb4443` | |
| `dist/index.d.mts` raw |
`b5e8dc982b634f0a5108b1b533626a68767f2da5a56f72dba801059b149e2872` | 0 |
| `dist/index.d.mts` normalised |
`562d0a4ce656f97aeb937541482cdf531b61d7c75a005918784bf0a52d032dfc` | |
- The normaliser, verbatim (the ruling's one-liner): `node -e 'const
s=require("fs").readFileSync(process.argv[1],"utf8");process.stdout.write(s.replace(/"[^"\n]*"(?:\s*\|\s*"[^"\n]*")+/g,r=>r.split(/\s*\|\s*/).sort().join("
| ")))' dist/index.d.ts | sha256sum`.
- The raw files are byte-identical, so no union-order swap occurs: items
1(b) and 1(d) hold with nothing to account for.
- **Positive control:** the head `dist/index.d.ts` with one private
member made public (`private createAuthInstance;` →
`createAuthInstance;`, line 1712, a one-line change) hashes raw
`35b18682171cd394898c9e56bc8d5272ccf20aeff0d1966fc568cb5e566a08df` and
normalised
`e69c1b0157b45e48bbc16bd64eb939abf9be33ccb31553485df93ef05aac6fc3`. Both
differ from the readings above.
- **Export lists:** ESM `dist/index.mjs` and CJS `dist/index.js` each
have 159 names at base and at head, the same list (the sha256 of the
sorted names is `3abb126f5babb701…` on all four). `globalAfterHook` and
`AfterHookHost` are not among them, and `dist/index.d.ts` names neither.
- **The bundle:** 18 files in `dist/` at both, the same list. Only
`index.js`, `index.mjs` and their two `.map` files differ, as a move of
code inside the bundle must. `tsup` bundles the new module into the root
entry (`splitting: false`).
**3. Tests and lint.**
- `pnpm exec vitest run --maxWorkers=3` in
`packages/plugins/plugin-auth`: base `Test Files 191 passed (191)`,
`Tests 3607 passed | 10 skipped (3617)`, exit 0. Head: the same counts,
exit 0.
- `pnpm --filter @objectstack/plugin-auth typecheck` (both `tsc`
projects and `check:test-typecheck`): exit 0. `pnpm --filter
@objectstack/runtime typecheck`: exit 0.
- `eslint --no-inline-config` (the root `lint` script's binary and
flags) over the 2 source files: exit 0.
**4. The censuses, the measurement and the anchors, at base and at
head.**
- The tenant-audit census, as above: byte-identical gate output, 238
sites at both, 0 per-site differences line-blind, 0 unresolved and 0
unledgered at both.
- `scripts/measure-durability-swallow-family.mjs` (a measurement, not a
gate): 77 members and 84 quiet rows at both. The members are the same
with line numbers ignored, and the quiet rows are identical. Only the
scanned file count moves (3,470 → 3,471, the new module).
`tryStatements` (3,639), `droppedNotAwaited` (239) and every other
statistic are the same: BODY's 4 `try` blocks move whole.
- These checkers were run by hand at base and at head, because
`dispatch-gates` does not derive the ADR one. All six exit 0 at both.
Five print byte-identical output at both (`cmp` clean):
- `check-adr-symbol-anchors`: 2,384 anchors across 142 records, 466
symbol (440 declaration, 26 literal);
- `check-scripts-symbol-anchors`: 4,070 anchors;
- `check-spec-docblock-symbol-anchors`: 5,076 anchors;
- `check-system-context-census`: 149 elevation read sites;
- `check-platform-checklist`: 16 areas, 329 items.
The sixth, `check-adr-anchors`, differs only in the file count and the
decision letters, as in the table above.
**5. Gates.**
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives 54 commands for the 2 paths. All 54
ran at head after the full build, and all 54 exited 0.
- `--ran` over the record with each exit code: 54 derived, 54 run, 0
NOT-MEASURED, a derived zero. `--tier`: no path-derived mandate.
- `check-governed-merges.mjs --branch HEAD`: NOT governed, 467 changed
lines.
- **Docs drift** (`node scripts/docs-audit/affected-docs.mjs --json
1ff43b6`, exit 0): 0 pages name something this change touched (19
anchors across `plugin-auth`), and 0 release-owned pages. So no doc edit
is owed.
- **Serial constraints** (in the claim): 11 PRs are open, and none
touches `auth-manager.ts`, the new module's path, or a reader named
above. The Version Packages PR #24876 touches `plugin-auth`'s
`package.json`, its `CHANGELOG.md` and changesets only. #25530 adds one
`scripts/adr-anchors/` entry for a `plugin-security` file, which moves
`check-adr-anchors`' totals for whichever lands second, but not this
cut's four letters. `origin/main` has moved 2 commits past this base, to
`74496c64b0` (#25526 `plugin-approvals`, #25527 `service-settings`).
Neither touches `plugin-auth` or `scripts/`.
## Changeset
None: `skip-changeset`, per ruling `6348891160` item 4. The published
declarations and export lists are unchanged, and the bundle's bytes move
only because code moved inside it.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01LSXBc2GCBwiAL7vV4kWkyr)_
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01LSXBc2GCBwiAL7vV4kWkyr
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 0fab7ba commit 93a6ba4
2 files changed
Lines changed: 274 additions & 193 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
0 commit comments