Repository navigation
Commit 2bcd5cf
Fixes #20193
Clause-②: yes
The runtime dispatcher's `/meta` item read and its `/published` read now
use the per-caller read gate that `RestServer` uses. It is one function
with two callers. `RestServer`'s gate moved unchanged into
`packages/rest/src/meta-item-read-gate.ts`, and `handleMetadataRequest`
calls it. There is no second audience resolver in `packages/runtime`, as
ruling `5793362670` item 1 requires.
#20156 remains open (its pending decision on the partial `app` cells of
`/layers`, `?layers=true` and `/diff` is untouched here). #20139 remains
open.
## The measurement that picked route A
Triage said the choice between B and A is a measurement. Here it is.
### Host census: which in-repo host compositions reach
`handleMetadataRequest`'s item branch
| host composition | REST mounted? | who answers `GET /meta/:type/:name`
| can REST be mounted there? |
|:--|:--|:--|:--|
| `@objectstack/hono` `createHonoApp` (published; README and
`content/docs/plugins/packages.mdx` name it the edge / serverless
adapter) | **no** | **the dispatcher**: `app.all(prefix + '/*')`, then
`dispatch()`, the domain registry, and `handleMetadataRequest` | **No,
as shipped.** `RestServer` registers on an `IHttpServer` (`http.server`
service). `createHonoApp` builds a bare Hono app whose catch-all is
terminal by design (ADR-0076, open question 9), and `@objectstack/hono`
does not depend on `@objectstack/rest`. |
| a thin adapter on the public `HttpDispatcher` API (`packages.mdx`:
"build a thin adapter on the public `HttpDispatcher` API") | no | the
dispatcher (`dispatch()` / `handleMetadata()`) | No, by construction |
| `plugin-hono-server` + `createRestApiPlugin` +
`createDispatcherPlugin`: the CLI's `serve` / `dev`
(`packages/cli/src/commands/serve.ts`) and `plugin-dev` | yes |
`RestServer`. `createDispatcherPlugin` mounts explicit routes and **no**
`/meta` route, so the dispatcher item branch is never reached | already
mounted |
| `packages/qa/http-conformance` `node:http` reference adapter (private
QA) | yes | `RestServer` | already mounted |
| `packages/verify` handle | no | never reaches `/meta` (it dispatches
`/automation` and `/actions` only) | n/a |
| cloud hosts (`objectstack-ai/cloud`, per ADR-0076 item 9: plugin
routes with the `createHonoApp` catch-all underneath) | yes |
`RestServer` first; the dispatcher answers REST misses | NOT MEASURED
here: another repository |
Reading. The documented embed shape cannot mount REST, and ADR-0076 item
9 records the dispatcher's `/meta` branches as "the cloud fallback
fabric, not dead code", not killable while the catch-all stands. So
**B** (retire the dispatcher's item reads) would remove a published
answer (`meta.getItem` / `meta.getPublished` in the route ledger) from a
documented host, and would reverse an accepted ADR. **A** is the route:
one transport-neutral gate that both transports call. **C** is ruled out
by `5793362670`.
### What the two item reads serve (B's scope, for the record)
- **Dispatcher item branch:** `GET` / `HEAD /meta/:type/:name`,
`/published`, `?package=`, `?preview=draft`, and a
`MetadataService.getItem` fallback. The body is enveloped `{ success,
data }`. Objects get the ADR-0106 mask on the plain read.
- **REST:** the same two reads, plus `/layers`, `?layers=`, `/history`,
`/audit`, `/diff`, `/references`, `?state=draft`, locale collapse
(`resolveDocLocale` / translation), and ETag / 304 on the cached arm.
The body is the bare `{ type, name, item, … }` envelope.
Route A retires nothing, so no answer is dropped. The item branch keeps
every one of its own parameters.
## Before and after
All rows are driven through `dispatch()`, the delegate of
`createHonoApp`'s catch-all: identity resolution, the domain registry
and the handler. The caller is an authenticated member who does not hold
`crm_admin`, on the fixtures of the REST door census
(`meta-alternate-door-read-gates.test.ts`). The "before" column is at
base `7e7fab73`. The "after" column is at head `0fcb064a2`, and the
first five rows were also re-read through a **real `createHonoApp` app**
(`app.request(…)`, a real `HttpDispatcher`, as a one-off probe that is
not committed).
| request (non-holder) | before | after | `RestServer`, same caller |
|:--|:--|:--|:--|
| `GET /meta/doc/crm_admin_runbook` | 200 + the gated body | **403
`PERMISSION_DENIED`** | 403 `PERMISSION_DENIED` |
| `GET /meta/doc/crm_admin_runbook/published` | 200 + the gated body |
**403 `PERMISSION_DENIED`** | 403 `PERMISSION_DENIED` |
| `GET /meta/book/admin_guide` (set-gated) | 200 + the book | **403
`PERMISSION_DENIED`** | 403 `PERMISSION_DENIED` |
| `GET /meta/app/crm` | 200, 3 entries | **200, `[nav_leads]`** | 200,
`[nav_leads]` |
| `GET /meta/app/crm/published` | 200, 3 entries | **200,
`[nav_leads]`** | 200, `[nav_leads]` |
| `GET /meta/book/admin_guide/published` | 200 | 403 `PERMISSION_DENIED`
| 403 |
| `GET /meta/app/payroll` (+ `/published`) | 200 | 403
`PERMISSION_DENIED` | 403 |
| `GET /meta/app/launchpad` (unpublished, + `/published`) | 200 | 404
`RESOURCE_NOT_FOUND`, byte-identical to a missing name on this transport
| 404 `RESOURCE_NOT_FOUND` |
| `GET /meta/dashboard/ops` (+ `/published`, holder too) | 200, both
widgets | 200, `[w_open_cases]` | 200, `[w_open_cases]` |
| `GET /meta/object/invoice/published` | 200, `[amount, secret_margin]`
| 200, `[amount]` | 200, `[amount]` |
| `GET /meta/docs/crm_admin_runbook` (plural) | 200 + body | 403
`PERMISSION_DENIED` | 403 |
Controls, unchanged: a holder reads the doc body (both doors), the book,
and the whole app. `GET /meta/object/invoice` is masked for the member
and served whole to the exempt holder. An anonymous caller gets `401
UNAUTHENTICATED` before any read.
Through the real `createHonoApp`, at head: non-holder doc / doc
`/published` / book → `403 PERMISSION_DENIED` with no secret on the
wire; app and app `/published` → `200 [nav_leads]`. Holder: `200` with
the doc and book bodies, and all 3 app entries.
## How
- **`packages/rest/src/meta-item-read-gate.ts` (new).**
`createMetaItemReadGate(sources, metaType, name, documents, policy)` is
the former `RestServer#metaItemReadGate` body. The helpers it calls came
with it unchanged: `filterAppForUserWithReason`,
`filterDashboardForUser`, `resolveDocsAudience`,
`resolveAudienceCaller`, the fault-reporting books and doc-corpus reads,
`resolveRegisteredServices`, `resolveNavServability`,
`resolveNavDocAudience` and `loadObjectItems`. Its verdict is **data**
(`serve`, or `refuse` with `absent` / `app-permission` /
`docs-audience`). Each transport supplies only I/O
(`MetaItemReadGateSources`): the caller, a list read, the security
service, a service probe, and a prune-log dedupe set.
- **`RestServer`** keeps every private helper name as a one-line
delegate, so its list routes, book tree and doors call the same code.
`metaItemReadGate` maps the data verdict to the emitters it always used
(`sendMetaItemAbsent`, `sendError`, `sendDeclaredFault`). REST's answers
are byte-for-byte unchanged: the 196-case door census and the rest of
the package's 3,558 tests pass.
- **`handleMetadataRequest`** calls the gate on whichever lookup answers
the item read and `/published`. The call sits *outside* the lookups' own
swallowing `try`s, so a gate fault is answered as that fault and never
as "not found". It uses policy `{ arms: 'all', app: 'gate' }`, the same
one `RestServer`'s plain read and `/published` use. Refusals use the
dispatcher's own envelope with `RestServer`'s status and code. `absent`
is the same `deps.error('Not found', 404)` a missing name gets.
- **`@objectstack/rest` exports** `createMetaItemReadGate` and its
types. This is the same pattern as `repeatedQueryParamMessage`: the
decision travels, nothing transport-shaped does.
**Also closed in the same claimed branch (bounded in-place fix, all four
conditions hold).** The dispatcher's `/published` did not apply the
ADR-0106 object mask that its own plain read applies. `GET
/meta/object/invoice/published` served `secret_margin` to a member whose
readable set is `[amount]` (row above). This is the same defect class:
this transport's `/meta` item doors skipping a per-caller read gate that
`RestServer` applies. The fix is mechanical: the dispatcher's existing
`maskObjectSchema` call, ordered after the gate as in `RestServer`'s
`/published`. It is in the claimed `/published` branch and pinned by the
same census. The card's own reading assumed "objects are masked here".
That held for the plain read and not for `/published`.
## Tests (head `0fcb064a2`)
- **Pin:**
`packages/runtime/src/domains/meta-item-read-gate-parity.test.ts`, 77
cases. It drives the same fixtures through `dispatch()` and through
`RestServer`. For each caller (holder, non-holder, anonymous) it asserts
equal `status` + `code` and the same served document (nav ids, widget
ids, field names, secrets present or absent) on the plain read and on
`/published`, for doc, book, app ×3, dashboard, object and view. It also
asserts the reference answers `RestServer` gives, plus five controls.
- `pnpm --filter @objectstack/runtime exec vitest run --project local`:
**280 files, 3986 passed, 1 skipped**.
- `pnpm --filter @objectstack/rest exec vitest run --project local`:
**200 files, 3558 passed, 1 skipped**.
- `pnpm --filter @objectstack/rest typecheck` and `pnpm --filter
@objectstack/runtime typecheck`: exit 0. Both test layers are OK, with
the runtime debt ledger unchanged.
- The `execctx-consumer-census` counts move by the gate's relocation: 70
→ 68 sites and 93 → 92 mentions. Three same-line-caught sites left with
the gate, and one caught caller port replaced them. Each number carries
its arithmetic in the test.
**Ablation.** The fix was committed first. Each leg went through
`scripts/ablation-replace.mjs` (WRAP mode, anchor hit 1 → 0, blob
changed), with a shell `trap` restore, and each restore was proven by
blob equals `HEAD` and an empty `git diff HEAD`. The subject resolves
from `src`: `../http-dispatcher.js`, and `@objectstack/rest` is aliased
to `src` in the runtime vitest config, so no `dist` leg applies.
- Gate leg (`gateMetaItemDocument` serves without judging): **16 red.**
These are all 14 non-holder / dashboard parity rows of the before-table
plus the plural and unpublished-app controls. The object `/published`
row stays green because it is the mask's.
- Mask leg (`/published`'s `if (publishedMasker)` disabled): **1 red**,
`GET /meta/object/invoice/published × non-holder`.
- Restore leg, unmutated: **77/77 green.** The direction was the
expected one: red.
**Gates.** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands` derived 70 commands for these 9
paths. All 70 exited 0 at `0fcb064a2`, and `--ran` reconciled them: 70
derived, 70 run, 0 NOT-MEASURED (a derived zero from recorded exit
codes). Also at that head:
- `pnpm lint`: full run, exit 0, 142 s.
- `node scripts/check-issue-citations.mjs --base origin/main`: exit 0.
- These roster and wide-population gates, which read these directories,
all exited 0: `check-changeset-fixed`, `check-published-list-mirrors`,
`check:error-code-casing`, `check:route-ledger-census`,
`check:published-readme-exports`, `check:meta-type-normalized`,
`check:init-service-contract`, `check:startup-registry-verdict`,
`check:wildcard-fallthrough`, `check:optional-error-sink`,
`check:filter-alias-parity`, `check:console-injection`,
`check:i18n-stale-fill`.
`check:doc-authoring` first went red for a moved string. The nav-prune
log line carried `[#7912]` into the new file. The id now sits in an
adjacent `//` comment, and
`scripts/doc-authoring-prose-id.baseline.json` shrinks by that one
pinned pair (`--census-ledger`, shrink only).
## Patch round 1 (head `acb99baa9`)
Contract review `5856229893` answered FAIL on `0fcb064a2`, and the
seat's REWORK is `5856245736`. This round makes three changes and merges
`origin/main` (`6d38c526f`, then `acb99baa9`).
1. **Liveness ledger re-anchored.** This fixes the `Test Core (1/6)`
red: 「8 anchored citation(s) name a symbol the cited file does not
contain」. Each pointer was re-measured against the site that now reads
the key, and its entry is stamped `verifiedAt: 2026-09-27`.
- `app.json` `navigation.requiredPermissions` and
`navigation.requiresService` now point at
`meta-item-read-gate.ts#filterNav`.
- `book.json` `name` now points at
`meta-item-read-gate.ts#deriveImplicitPackageBook` (the `bookNamed`
lookup).
- `doc.json` `name` now points at
`meta-item-read-gate.ts#resolveDocAudiences` (`docReader`:
`audiences.get(docName)`). `order` and `group` point at
`meta-item-read-gate.ts#docCorpusOf`, the list-branch corpus projection.
- `doc.json` `description` and `tags` point at
`rest-server.ts#readableTree`. The tree route's `{ name, label,
description, order, group, tags, packageId }` projection stayed in
`rest-server.ts`, and the new file does not name `description` at all:
the key-mention check refused that first repoint. So the pointer names
the site that reads the key. `tags` also points at
`meta-item-read-gate.ts#resolveBookTree`.
- Also moved, although they still resolved as text (a docblock mention
in `rest-server.ts` satisfied the anchor):
- `app.json` `requiredPermissions`, `_unpublished` and the file's
`_note` now point at
`meta-item-read-gate.ts#filterAppForUserWithReason`;
- `book.json` `audience` now points at
`meta-item-read-gate.ts#audienceAllows` (`admitsBook`);
- `dashboard.json` `widgets.requiresService` now points at
`meta-item-read-gate.ts#filterDashboardForUser`.
- Left alone: row 18 of
`docs/adr/0056-permission-model-landing-verification.md` cites
`rest-server.ts#filterAppForUser`. That is still a live declaration (the
delegate REST's list route calls), and the file is a governed surface.
- Results: `pnpm --filter @objectstack/spec run check:liveness` exit 0
(「758 pointer(s) written `path#symbol`, 758 naming a symbol the cited
file contains」). `scripts/liveness/check-liveness.test.ts`: 64 passed,
where 21 were red in CI. All `scripts/liveness/` tests: 252 passed
(local project) and 81 passed (repo project).
2. **`Clause-②: yes`.** `@objectstack/rest`'s only export subpath gains
`createMetaItemReadGate` and five types: `MetaItemReadGateSources`,
`MetaItemReadVerdict`, `MetaItemReadRefusal`, `MetaReadGateCaller` and
`MetaReadGatePolicy`.
- They are public because the runtime dispatcher consumes this one gate,
and `@objectstack/rest` cannot import the runtime.
- Precedent: #17672 / PR #17815.
- The changeset now carries the declaration line and names the exports.
The bumps are unchanged.
- `node scripts/check-adr-0087-registration.mjs --base origin/main`:
exit 0. `node scripts/check-changeset-no-major.mjs --base origin/main`:
exit 0.
3. **Composed-host pin, committed:**
`packages/qa/http-conformance/src/hono-meta-item-read-gate.conformance.test.ts`,
7 cases. It boots a real `LiteKernel` and the real `createHonoApp`, and
drives them with `app.request(...)`.
- Non-holder: the doc, the doc's `/published` and the set-gated book
answer `403`, with `error.code` `PERMISSION_DENIED`, `success: false`
and no secret on the wire. The `crm` app answers `200`, pruned to
`[nav_leads]`.
- The holder control is served all four in full.
- **Why this package and not `packages/adapters/hono`:** that package's
`vitest.config.ts` aliases `@objectstack/runtime` to a stub
(`src/__mocks__/runtime.ts`) for every test. `createHonoApp` imports
`HttpDispatcher` from that specifier, so a host composed there would
compose the stub. `http-conformance` is where the repo already boots the
two for real (`hono-dispatcher-result-response.conformance.test.ts`):
`@objectstack/hono` is aliased to source, and the runtime resolves
through `dist/`, a ledgered pair in `check-test-source-alias`.
- **Per-PR tier:** `@objectstack/http-conformance` is in `turbo ls
--affected` for this diff, because it depends on `@objectstack/runtime`
and `@objectstack/hono`. `Test Core`'s PR shards therefore collect it;
they exclude only `@objectstack/dogfood`.
- **Ablation (through `dist/`).** The mutate leg replaced the gate call
`verdict = await judge(document);` with a serve-as-stored verdict
carrying the marker `ablated20193`, then rebuilt the runtime.
`ablation-dist-preflight` found the marker in `dist/index.js` and
`dist/index.cjs`. Result: **4 failed | 3 passed**, exactly the four
non-holder rows red and the holder controls green. The restore leg put
the file back (blob equals `HEAD`, `git diff HEAD` empty), rebuilt, and
`--absent` found no marker with a clean tree. Result: **7/7**. Both legs
ran at `b58d036ed` and again at `acb99baa9`.
**Verification at `acb99baa9`:**
- runtime local tests: 281 files, 4016 passed, 1 skipped;
- rest local tests: 201 files, 3576 passed, 1 skipped;
- `@objectstack/hono`: 5 files, 122 passed;
`@objectstack/http-conformance`: 7 files, 96 passed;
- both typechecks: exit 0;
- `pnpm lint`: exit 0;
- `node scripts/check-issue-citations.mjs --base origin/main`: exit 0;
- `dispatch-gates --commands` derived 77 commands, all ran, and `--ran`
reconciled 77 of 77 with exit codes (0 NOT-MEASURED).
## Changeset
`.changeset/20193-dispatcher-meta-read-gate.md`:
- **`@objectstack/runtime`: `patch`.** A fix in a released package
(Post-Task Checklist step 3).
- **`@objectstack/rest`: `minor`.** It adds public exports
(`createMetaItemReadGate` and five types), the same bump the changeset
for `repeatedQueryParamMessage`'s publication took. REST's own behaviour
is unchanged.
`Clause-②: yes`: `@objectstack/rest`'s published export surface widens.
Its only export subpath gains `createMetaItemReadGate` and five types,
which are public because the runtime dispatcher consumes this one gate
(precedent #17672 / PR #17815). The dispatcher's refusals themselves are
not the widening: they pull a second transport back to the gate the
contract already declares (ADR-0046 §6.7, ADR-0045 §3, ADR-0106,
`apps.mdx`'s `requiredPermissions` row). No accept set widens, and
nothing authorable moves. ADR anchor added:
`scripts/adr-anchors/packages__rest__src__meta-item-read-gate.ts.json`
(ADR-0045, ADR-0046).
## Acceptance notes
- **Same family, outside this card's claimed surface: the dispatcher's
`/meta/:type` LIST read is ungated too.** Measured through `dispatch()`
for the same non-holder at head:
- `GET /meta/doc?include=content` → 200, `crm_admin_runbook` **with its
body**;
- `GET /meta/book` → 200, `admin_guide` with its description;
- `GET /meta/app` → 200, `payroll` (app-level `requiredPermissions`) and
`crm` with `nav_finance_ledger`.
`RestServer`'s list route answers `[crm_intro]`, `[]` and `[crm]`
pruned. Fixing it needs `RestServer`'s LIST filters extracted the same
way, which is a second seam and not mechanical, so it was filed
separately as #20237 rather than folded in here. #20237 remains open.
- The before-table was taken through `dispatch()`. Through a real
`createHonoApp` host, the four rows are now a committed pin
(`hono-meta-item-read-gate.conformance.test.ts`). Its ablation leg, with
the gate call removed and the runtime rebuilt, is the Hono-level
*before* reading: the four non-holder rows go red, and the holder rows
stay green.
- A host whose `protocol` has no `getMetaItems` now answers a doc or
book item read with the fault (fail closed, ADR-0049) instead of the
ungated body. `RestServer` has the same requirement.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01UYBdGBzWSrAMzpW8ah3GbP)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 14ae40b commit 2bcd5cf
14 files changed
Lines changed: 2427 additions & 1154 deletions
File tree
- .changeset
- packages
- qa/http-conformance/src
- rest/src
- runtime/src/domains
- spec/liveness
- scripts
- adr-anchors
| 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 | + | |
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
310 | 310 | | |
311 | 311 | | |
312 | 312 | | |
313 | | - | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
314 | 327 | | |
315 | 328 | | |
316 | 329 | | |
| |||
423 | 436 | | |
424 | 437 | | |
425 | 438 | | |
426 | | - | |
427 | | - | |
| 439 | + | |
| 440 | + | |
428 | 441 | | |
429 | 442 | | |
430 | | - | |
431 | | - | |
432 | | - | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
433 | 446 | | |
434 | 447 | | |
435 | 448 | | |
436 | 449 | | |
437 | 450 | | |
438 | 451 | | |
439 | | - | |
440 | | - | |
| 452 | + | |
| 453 | + | |
441 | 454 | | |
442 | 455 | | |
443 | 456 | | |
444 | 457 | | |
445 | | - | |
| 458 | + | |
446 | 459 | | |
447 | 460 | | |
448 | 461 | | |
| |||
709 | 722 | | |
710 | 723 | | |
711 | 724 | | |
712 | | - | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
713 | 731 | | |
714 | 732 | | |
715 | 733 | | |
| |||
0 commit comments