Repository navigation
Commit 860f002
<!-- 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
The basis for the `Clause-②: no` line: this is a move. No accept set,
export, route, refusal, code or answer changes. The `.d.ts` bar is
ruling `6348891160` item 1 (on #25222, covering this card).
`@objectstack/plugin-auth`'s published `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), with the ruling's positive
control. Its entry exports the same 155 names under ESM and CJS
(measured below).
Cut 6 of the `auth-manager.ts` split: **the plugin assembly helpers.**
Three `AuthManager` method bodies (85 lines) move unedited, re-indented
one level, into one new module,
`packages/plugins/plugin-auth/src/auth-manager-plugin-assembly.ts`.
#25224 stays open for the later cuts.
This follows the amended claim `6361212912`, which amends `6359424739`
on the file cut 5 left (#25395, landed note `6360455119`). The shape is
cuts 1 to 5's, which is #23050's.
Branch: `claude/project-thread-lg3wrj`, the harness-pinned branch for
this session, restarted from `origin/main` `eca6b61922` after #25395
merged. It names no issue, so the card relation is this body's first
line.
`auth-manager.ts` goes from 8,968 to 8,916 lines. The cut is +202 / −89
over 2 files: 291 changed lines, under the 3,000-line line. It is not a
governed surface (`check-governed-merges.mjs --branch HEAD`: 0 of the 2
paths hit the register).
## Why this seam
These are the three helpers `buildPluginList` calls to assemble
better-auth's plugins:
- `addOptionalPlugin`: one optional plugin whose construction throws is
skipped, recorded in `degradedFeatures` and logged, so it cannot take
down core email/password and session auth (the 15.1.0 incident its
docblock records);
- `buildJwtPlugin`: the `jwt` plugin, built with a signing algorithm
this host can use (the Ed25519 probe), the signing-key reader, and the
`/get-session` header hook made non-fatal;
- `reportJwtSigningFailure`: the record and once-per-build announcement
of a JWT signing failure that hook catches.
What stays, and why:
- `resolvePasswordHasher` stays. Its body reads `isWebContainerRuntime`,
a module-level function that `auth-manager.ts` does not export and that
`installWebContainerRequestStatePolyfill` also reads. `index.ts`
re-exports `auth-manager.ts` whole (`export * from
'./auth-manager.js'`), so exporting it there would publish it, and
moving it would move a declaration the polyfill shares. Per the landed
note `6360455119`, a body that reads an unexported module helper comes
back as `needs_decision` before it is cut.
- `getDegradedAuthFeatures` stays: it is the public, one-line read of
the record `addOptionalPlugin` writes.
- `buildPluginList`, which calls all three, is a later cut.
- `createDatabaseConfig`, `resolveAuthSecret` and `generateSecret` are
the database and secret `createAuthInstance` hands better-auth, a
different area, so they take their own cut. The seat agreed both splits.
## What moved
| method | base signature line | body lines | members it reads |
|---|---:|---:|---|
| `addOptionalPlugin` | `:3178` | 15 | `degradedFeatures` |
| `buildJwtPlugin` | `:3242` | 55 | `config`, `ed25519ProbeResult` (read
and written), `reportJwtSigningFailure` |
| `reportJwtSigningFailure` | `:3308` | 15 | `degradedFeatures`,
`jwtSigningFailureReported` (read and written) |
Lines are base `eca6b61922`. The members come from a walk of every
`this.X` in each body with the TypeScript compiler API. No body has a
bare `this`, `this[...]`, `arguments` or `super`, or a `this` inside a
`function` or a nested class. No body reads a static (`AuthManager.X`)
or a module-level declaration of `auth-manager.ts`. The two assignments
to a `this` member are `buildJwtPlugin`'s to `ed25519ProbeResult` and
`reportJwtSigningFailure`'s to `jwtSigningFailureReported`.
**Imports.** Six imported names are read only by the moved text, so they
leave `auth-manager.ts` and the new module imports each from the same
place:
- `buildJwtPluginSchema` (`./auth-schema-config.js`, still imported by
`auth-manager.ts` for ten other names);
- `createSigningKeyReader` (`./signing-key-read-cache.js`, still
imported there for `retireHeldKeyrings` and
`UNKNOWN_SIGNING_KEY_REREAD_FLOOR_MS`);
- `createHostUsableJwksReader`, `probeEd25519Support`,
`protectGetSessionJwtHook` and `resolveJwtSigningAlgorithm`
(`./jwt-key-algorithm.js`).
**Evaluation order.** `auth-manager.ts` no longer imports
`./jwt-key-algorithm.js` itself. Nothing observable moves: that module
has no imports, and its top level is three `as const` object literals, a
type alias, interfaces and function declarations, so the point at which
it is evaluated cannot be observed. `signing-key-read-cache.ts` imports
it type-only.
## The shape
- **The class keeps all three methods** at their places, with their
names, signatures and docblocks: the published `.d.ts` lists each one.
Each body is now a host literal of exactly the members that body reads,
typed as a `Pick` of `PluginAssemblyHost`, plus `.call`.
- **`PluginAssemblyHost`** lives in the new module. It names the 5
members the bodies read, each typed as the class member
(`AuthManager['degradedFeatures']`, …). The module imports `AuthManager`
as a type only, so there is no runtime cycle.
- **`reportJwtSigningFailure` goes as a late-bound closure** (`(...a) =>
this.reportJwtSigningFailure(...a)`). The `/get-session` guard calls it
at request time, long after `buildJwtPlugin` returned, and still reaches
the method on the manager, so a spy or double set there is still the one
it reaches.
- **`config` and `degradedFeatures` go as getters.** The class reassigns
`config` after construction (`setRuntimeBaseUrl`, `applyConfigPatch`),
so it is read off the manager when a body reads it, as before.
`degradedFeatures` is read the same way.
- **`ed25519ProbeResult` and `jwtSigningFailureReported` go as get/set
pairs.** The bodies store to both on the manager. So the Ed25519 probe
still runs once per manager, the `() => this.ed25519ProbeResult!` thunk
still reads the manager's promise when better-auth calls it, and a
signing failure is still announced once per plugin-list build, which
resets the flag (`buildPluginList`, which stays).
- **Two stubs are no longer `async`.** Each returns the moved async
function's own promise, so a caller awaits the same promise the body
settles. Building the host cannot throw, so no method now throws
synchronously where it used to reject. `reportJwtSigningFailure` was
synchronous and stays so.
- **The cost:** one small host object per call. `buildJwtPlugin` and
`addOptionalPlugin` run once per plugin-list build;
`reportJwtSigningFailure` runs only on a signing failure.
- **Nothing re-exports the new module**, so the published surface does
not move.
## Path readers
None needs migrating: no reader keys on a moved line. Measured as
reading no moved line:
- **`api-error-code.pin.test.ts`'s `authManagerFiles` floor**: no `new
APIError(` sits in the moved bodies, so the floor reads the same sites
over the same files at base and head, and the new module is not added to
the list.
- **Plugin-factory scans** in `better-auth-schema-parity.test.ts` and
`managed-extension-fields.test.ts`: the moved text has no `await
import(`. `buildJwtPlugin` takes the `jwt` factory as a parameter, and
the factory's import stays in `buildPluginList`.
- **`check-dispatcher-error-vocabulary.mjs`**,
**`check-auth-mount-ledger.mjs`** and
**`auth-manager-base-path.test.ts`**: none of the tokens they read sits
in the moved text. `check-dispatcher-error-vocabulary` reads 56 sites
found and 56 classified at base and at head.
- **The tenant-audit census** and its two documents: the moved text
holds no engine write. Compared per site, base and head read the same
237 sites with the same totals (below), so neither document is
regenerated.
- **The system-context census**: the moved text holds no `isSystem`
read. The census reads 148 elevation read sites at base and at head.
- **`scripts/adr-anchors/`**: the moved text cites no ADR, and no
entry's invariant describes it. The `auth-manager.ts` entry (ADR-0093
and ADR-0108) is unchanged and still holds.
- **Callers through the manager**: the suites that drive the three
methods, among them `auth-manager.jwt-eddsa-fallback.test.ts` (the host
without Ed25519, an existing EdDSA key hidden and never deleted, and the
signing failure recorded and announced once) and
`auth-manager.optional-plugin-isolation.test.ts` (a throwing optional
plugin skipped while sign-up and get-session still answer, and the
degraded state reset on rebuild), call each through the class method.
All pass at head (below).
- **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, in ADR-0127, ADR-0134,
ADR-0135 and four platform-checklist areas, and all 29 are
`declaration`-class at base, with the 3 bodies blanked, and at head.
None names a moved method. One names a token the moved text also
carries: `#AuthManager` (ADR-0135), in the bodies' `[AuthManager]` log
prefixes. It resolves on the class declaration, which stays.
- **`check-adr-anchors`' decision-letter layer** (the seat asks each
cut's report for this count at both ends): 2,016 citations at base and
2,016 at head. The moved text carries no `ADR-NNNN Dk` citation, so
nothing leaves the anchored surface. The number layer reads 52,116
citations across 6,623 files at both. On `origin/main` `7c68b10825`
(below) the layer reads 2,014 alone and 2,014 with this cut.
## Proof
Builds and suites ran through `os-verify-lock`, and every exit code was
captured before any pipe. Base `eca6b61922`, head `eda6277866`. A full
`turbo run build` ran first. Then `plugin-auth` was built and its suite
run at base, then built and run at head, on the same dependency dists.
**1. The moved text.**
- For each of the 3 methods, the base class body and the new module's
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).
- Every line is the base line minus exactly two leading spaces, and the
parameters and return type are the same text.
- Each class method keeps its docblock and signature, with `async`
dropped from the two that had it.
- Result: 3 of 3 pass, 85 body lines.
| method | body lines | tokens |
|---|---:|---:|
| `addOptionalPlugin` | 15 | 87 |
| `buildJwtPlugin` | 55 | 168 |
| `reportJwtSigningFailure` | 15 | 67 |
- **Negative control:** one token changed in the module (`'jwtSigning'`
→ `'jwtSigned'` in `reportJwtSigningFailure`) makes that method fail
(tokens and lines DIFFER), and the run exits 1. Restored afterwards;
`cmp` against the saved copy was clean.
- **An independent reading:** `git diff --color-moved=plain
--color-moved-ws=allow-indentation-change eca6b61 eda6277` over
the two source files marks 85 of the 89 deleted lines and 96 of the 202
added lines as moved.
- The other 4 deleted lines are the two `async` signature lines and two
import-name lines (`buildJwtPluginSchema`, `createSigningKeyReader`).
The `./jwt-key-algorithm.js` import block is marked moved: the module
carries it verbatim.
- The other added lines are the stubs' host literals,
`PluginAssemblyHost`, the module header, the per-function pointer
docblocks and the import blocks.
**2. `.d.ts` and exports (ruling `6348891160` items 1 and 2).**
| file | raw base | raw head | raw diff lines | normalised base |
normalised head |
|---|---|---|---:|---|---|
| `dist/index.d.ts` |
`3b3aedb6551d6324c40d87afd1cdee50b23bcb2c3384c39a9f71b771deca0472` |
`3b3aedb6551d6324c40d87afd1cdee50b23bcb2c3384c39a9f71b771deca0472` | 0 |
`d4a901d16c32f4838c14dd7fdc52d88d9d446b4b1d44afd4012c81b365ef9783` |
`d4a901d16c32f4838c14dd7fdc52d88d9d446b4b1d44afd4012c81b365ef9783` |
| `dist/index.d.mts` |
`e2cdb2bc530cc6a554107866875910a90031e42fc89574d9adcb00d38a1becf1` |
`e2cdb2bc530cc6a554107866875910a90031e42fc89574d9adcb00d38a1becf1` | 0 |
`b2c585e677d5ac57274c22d746f6213342fbf1e7c8061b56b94175e8fe21c19d` |
`b2c585e677d5ac57274c22d746f6213342fbf1e7c8061b56b94175e8fe21c19d` |
- 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 already byte-identical, so no union-order swap
occurs in this cut: 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 buildJwtPlugin;` → `buildJwtPlugin;`, line
1881, a one-line change) hashes raw
`8eaebd38dabcfa33bbe0db93e6bd2c8836c91a169d81c8e6aa2ec4e78055b2de` and
normalised
`4c5bbc92792de5db2c8f1b89018fd45d4aea96fe43b7479e3c934db9069c6169`. Both
differ from the readings above.
- **Export lists:** ESM `dist/index.mjs` and CJS `dist/index.js` each
have 155 names at base and at head, the same list (the sha256 of the
sorted names is `ed3ac8b902031d30…` on all four).
- **The bundle:** 20 files in `dist/` on both sides, the same list. Only
`index.js`, `index.mjs`, their two `.map` files and the two build-input
hash stamps differ, as a move of code inside the bundle must.
**3. Tests and lint.**
- `pnpm exec vitest run --maxWorkers=3` in
`packages/plugins/plugin-auth`: base `Test Files 187 passed (187)`,
`Tests 3528 passed | 10 skipped (3538)`, VERDICT command-exit 0. Head:
the same counts, VERDICT command-exit 0.
- `pnpm --filter @objectstack/plugin-auth typecheck` (both `tsc`
projects and `check:test-typecheck`): exit 0.
- `eslint --no-inline-config` (the root `lint` script's binary and
flags) over the 2 files: exit 0.
**4. The census and the anchors, at base and at head.**
- The tenant-audit census (`node scripts/tenant-audit-census.mjs
--json`), compared per site with the new module's file name mapped back
to `auth-manager.ts`: 237 sites on both sides, 0 per-site differences in
object, verb, tenancy, context and elevation, 0 unresolved and 0
unledgered on both, and every total the same.
- 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,
with the same reading at both:
- `check-adr-symbol-anchors`: 2,384 anchors across 142 records, 466
symbol (440 declaration, 26 literal).
- `check-adr-anchors`: 80 anchored files; the decision-letter layer as
above.
- `check-scripts-symbol-anchors` (4,061 anchors),
`check-spec-docblock-symbol-anchors` (5,071 anchors, both read in the
same built tree), `check-system-context-census` (148 elevation read
sites) and `check-platform-checklist` (16 areas, 329 items).
**5. Gates.**
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derives 53 commands for the 2 paths. All 53
ran at `eda6277866` after the full build, and all 53 exited 0.
- `--ran`: 53 derived, 53 run, 0 NOT-MEASURED.
- `check-governed-merges.mjs --branch HEAD`: NOT governed, 291 changed
lines.
- **Docs drift** (`node scripts/docs-audit/affected-docs.mjs --json
eca6b61`, exit 0): 0 pages name something this change touched (11
anchors: 7 symbol, 4 literal).
- **Serial constraints** (in the claim): before the run, one open PR
touched `auth-manager.ts`, #25398, in the docblock of the
`enforceSessionControls` stub, not a line of this cut. It has since
merged, with #25381, #25396 and #25397, and `origin/main` is
`7c68b10825`. On that tree with this cut applied (no conflict):
- the move proof against `7c68b10825` passes 3 of 3;
- `check-tenant-audit-census`, `check-adr-anchors`,
`check-adr-symbol-anchors`, `check-platform-checklist`,
`check-system-context-census`, `check-auth-mount-ledger` and
`check-dispatcher-error-vocabulary` exit 0;
- the seven suites that drive the moved methods or read the file pass
(386 tests).
- One open PR now touches `auth-manager.ts`: #25399, inside
`createAuthInstance` and `buildPluginList`, not a line of this cut. `git
merge-tree` of this head with #25399's head is clean.
## 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 c6bdcac commit 860f002
2 files changed
Lines changed: 202 additions & 89 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
147 | 147 | | |
148 | 148 | | |
149 | 149 | | |
150 | | - | |
151 | 150 | | |
152 | 151 | | |
153 | 152 | | |
154 | 153 | | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | 154 | | |
163 | 155 | | |
164 | 156 | | |
| |||
230 | 222 | | |
231 | 223 | | |
232 | 224 | | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
233 | 233 | | |
234 | 234 | | |
235 | 235 | | |
| |||
3201 | 3201 | | |
3202 | 3202 | | |
3203 | 3203 | | |
3204 | | - | |
| 3204 | + | |
3205 | 3205 | | |
3206 | 3206 | | |
3207 | 3207 | | |
3208 | 3208 | | |
3209 | | - | |
3210 | | - | |
3211 | | - | |
3212 | | - | |
3213 | | - | |
3214 | | - | |
3215 | | - | |
3216 | | - | |
3217 | | - | |
3218 | | - | |
3219 | | - | |
3220 | | - | |
3221 | | - | |
| 3209 | + | |
| 3210 | + | |
| 3211 | + | |
| 3212 | + | |
| 3213 | + | |
| 3214 | + | |
3222 | 3215 | | |
3223 | 3216 | | |
3224 | 3217 | | |
| |||
3265 | 3258 | | |
3266 | 3259 | | |
3267 | 3260 | | |
3268 | | - | |
3269 | | - | |
3270 | | - | |
3271 | | - | |
3272 | | - | |
3273 | | - | |
3274 | | - | |
3275 | | - | |
3276 | | - | |
3277 | | - | |
3278 | | - | |
3279 | | - | |
3280 | | - | |
3281 | | - | |
3282 | | - | |
3283 | | - | |
3284 | | - | |
3285 | | - | |
3286 | | - | |
3287 | | - | |
3288 | | - | |
3289 | | - | |
3290 | | - | |
3291 | | - | |
3292 | | - | |
3293 | | - | |
3294 | | - | |
3295 | | - | |
3296 | | - | |
3297 | | - | |
3298 | | - | |
3299 | | - | |
3300 | | - | |
3301 | | - | |
3302 | | - | |
3303 | | - | |
3304 | | - | |
3305 | | - | |
3306 | | - | |
3307 | | - | |
3308 | | - | |
3309 | | - | |
3310 | | - | |
3311 | | - | |
3312 | | - | |
3313 | | - | |
3314 | | - | |
3315 | | - | |
3316 | | - | |
3317 | | - | |
3318 | | - | |
3319 | | - | |
3320 | | - | |
3321 | | - | |
| 3261 | + | |
| 3262 | + | |
| 3263 | + | |
| 3264 | + | |
| 3265 | + | |
| 3266 | + | |
| 3267 | + | |
| 3268 | + | |
| 3269 | + | |
| 3270 | + | |
| 3271 | + | |
| 3272 | + | |
3322 | 3273 | | |
3323 | 3274 | | |
3324 | 3275 | | |
| |||
3332 | 3283 | | |
3333 | 3284 | | |
3334 | 3285 | | |
3335 | | - | |
3336 | | - | |
3337 | | - | |
3338 | | - | |
3339 | | - | |
3340 | | - | |
3341 | | - | |
3342 | | - | |
3343 | | - | |
3344 | | - | |
3345 | | - | |
3346 | | - | |
3347 | | - | |
| 3286 | + | |
| 3287 | + | |
| 3288 | + | |
| 3289 | + | |
| 3290 | + | |
| 3291 | + | |
| 3292 | + | |
| 3293 | + | |
| 3294 | + | |
| 3295 | + | |
3348 | 3296 | | |
3349 | 3297 | | |
3350 | 3298 | | |
| |||
0 commit comments