| M1-70/0 |
2026-10-17 |
Base int/m1-wave38 at 297ab0c, branch feat/M1-70-leak-tests in its own worktree; the branch is not merged locally and not pushed, the PR lane lands it. The brief relies on no core rule or ruling that main has and the base lacks (AZ-P4, AZ-P5, AZ-P12, AZ-M52 and authz.not_found_timing_tolerance are in the base's 07 and configuration reference), so nothing is ported. The brief's 07-permissions.md is 07-rechte.md and its 03-data-model.md is 03-datenmodell.md on the base; the sentence this ticket adds to 07 is English, and the lint names its data model chapter in tools/lint/sql_visibility.yaml (data_model), so a port changes one line. |
Instructions of the launcher, which override the brief's merge step. |
| M1-70/1 |
2026-10-17 |
authz.not_found_timing_tolerance is planned, not in the server's schema; the timing test reads its standard from the table of docs/operations/configuration.md at run time (TestToleranceFromReference), never as a literal. AZ-P4 compares medians of timingSamples interleaved samples after timingWarmup warm-up pairs per route and requester (named constants in notfound_test.go). |
The server does not read the key; the reference is its only source, and the brief forbids a literal. Alternating the order cancels drift of a loaded host, as ID-T21 does. |
| M1-70/2 |
2026-10-17 |
On the tables spaces and channels the lint accepts their key id = ANY(<param>) as the visibility predicate (ListVisibleSpaces, ListVisibleChannels). |
The key of a space is its space_id; the brief's (channel_id\|space_id) names the column of the tables that reference them. |
| M1-70/3 |
2026-10-17 |
after_authorize covers a single resource and the rows of exactly one resource that authorize allowed (the threads or tags of one channel, the mentions of one message, the own read states of one thread or channel), keyed by its ID in the query. A list across several channels or spaces never takes an exception: ListSidebarStates read every sidebar row of the person and filtered only by authorize per row; it now carries (@all_spaces OR st.space_id = ANY(@visible)) from Scope (fix in chat, regression tests TestSidebarListCarriesScope and the repository test). |
A key of one allowed resource is a narrower predicate than = ANY($visible); a multi-resource list is exactly what rule 1 asks to filter in SQL. |
| M1-70/4 |
2026-10-17 |
Fixtures with ok=false exist only for user_id and a person as requester (05 user.read); every other path parameter has a foreign instance for both requesters. PrepareExtras creates what the matrix world lacks through the public API as the owner: a disabled trusted-header login driver, an app with a webhook subscription (webhook.allowed_hosts set to the receiver host; egress stays denied) and a host without assignee. World.Owner is added to the harness for it. |
Routes of apps, hosts, providers and webhook subscriptions are enabled in M1, so they need a real foreign instance, not a reason. |
| M1-70/5 |
2026-10-17 |
AZ-P5 property 1 checks every space, channel, thread, agent and message ID a surface or an event names against the per-item truth, except an agent ID in an operator member of a space or channel (default_operator_agent_id, operator.effective_agent_id, also in the payload of an older event): that is header data of a resource the principal reads (05 space.read, channel.read), not the agent card agent.read protects. Agents as items (listAgents, the agents of the snapshot) stay checked. |
Catch-up delivers older events of a now readable channel with the payload of their time (07 principle 4); the operator of that time is part of the channel then. Redacting it would change 04, which the brief forbids. |
| M1-70/6 |
2026-10-17 |
The AZ-P5 server sets authz.expiry_sweep_interval to 24h; expiring grants and memberships end expiryLead (a named constant of world.go) after their creation on the real clock, and the build waits until that has passed. The person writes drafts and read states before; the lost channel gets a write grant, a draft and read states and is revoked. Agents have no personal data in the snapshot (sync), so their unread list must be empty. listMyReadStates needs channel_id, so it is queried per channel; an unreadable channel must return no rows. |
Expiry is checked on every call (07 8.3); the sweep's access.changed would otherwise land between the two collections of property 2. A draft needs write. |
| M1-70/7 |
2026-10-17 |
Client.Gateway(ctx) returns (*GatewayConn, error) on wstest (hello, identify with the DPoP proof for the HTTPS form of the gateway URL, ready, Next, Send, Close, automatic heartbeat); reauth is not automatic. |
A test connection lives far shorter than an access token; wstest already holds the frame codec. |
| M1-70/8 |
2026-10-18 |
httpserver.SchemaValidator.Validate holds a mutex around the libopenapi call; the gateway shares one validator across all connections. |
go test -race of the leak tests (two gateway connections at once) reported a data race inside libopenapi's schema rendering; TestSchemaValidatorConcurrent reproduces it in the owning package. A mutex is the smallest fix; frame bodies are small. |
| M1-70/9 |
2026-10-19 |
Port onto main: code and tests as in the ticket range (297ab0c..a276c89a3) together with the integration fix INT-W40/1, except the points named here. Main has the port of M1-72, so test/harness/gateway.go keeps its GatewayConn (fields Hello and Ready, Next returning a Frame, own heartbeats, reauth, GatewayFrom) and gains only the identify with the API token of an agent; TestGateway and the leak tests read g.Ready and g.Hello as fields, and M1-70/7 is superseded by INT-W40/1 for the harness. The base held M2-24 and M2-39, which main does not have: the routes of apps, webhook subscriptions and hosts are not enabled on main and webhook.allowed_hosts is not a key of its schema, so PrepareExtras creates only the login driver, the fixtures app_id, subscription_id and host_id and ExtrasConfig are not ported, and TestAZ_P4_RouteCoverage fails with "no fixture" for the ticket that enables such a route, which adds its fixture (M1-70/4 stays for the login driver). The exceptions chat.ChannelIDsOfSpace (M3-18) and sync.EventBySeq (M2-24) of tools/lint/sql_visibility.yaml are not ported, because their queries are not on main and the lint fails a stale exception; they return with those tickets. data_model names docs/spec/03-data-model.md, the sentence of 07 stands in the English section 7.4 before the paragraph on the cost estimates, and the changelogs take only the entries of this ticket. The lint passes every query of main, including the ports of M1-62 to M1-66, M1-71 and M1-72. No migration. |
The base int/m1-wave38 held tickets that are not on main (for example M2-24, M2-26, M2-39, M3-13, M3-18, M4-18, M6-01); the port keeps the behaviour of the ticket and adapts only to what main has. |
| M1-70/10 |
2026-10-20 |
Port onto main after M2-24: the app routes are enabled, so PrepareExtras also installs an app without delivery as the owner, and app_id gets its fixture; Alex and Lotse are no owners, so the app is foreign to both (05 app.read). The webhook subscription routes stay without a fixture until their ticket. |
AZ-P4 requires a foreign instance for every path parameter of an enabled route; getApp and the other app routes came with M2-24. |
| M1-70/11 |
2026-10-20 |
Port onto main after M2-26: the webhook subscription routes are enabled, so PrepareExtras installs its app with messages:read, events:subscribe and message.created (11 section 3.2 rules 1 and 2) and creates a subscription of it as the owner (hooks.example.com, allowed through webhook.allowed_hosts in ExtrasConfig; EgressDenyAll keeps every delivery off the network), and subscription_id gets its fixture; Alex and Lotse are no owners, so the subscription is foreign to both (05 webhook.read). |
AZ-P4 requires a foreign instance for every path parameter of an enabled route; listWebhookDeliveries came with M2-26 and failed TestAZ_P4_RouteCoverage without a fixture. |
| M1-70/12 |
2026-10-21 |
Port onto main after M1-65, M1-71 and M1-72 (without M1-66 to M1-69): the ruling of the ticket on timing bounds is PL/21, because PL/13 to PL/20 are taken on main. chat.ChannelIDsOfSpace of M3-18 is a reviewed exception of the SQL visibility lint with the reason of the integration line (the ids of the channels of the one space whose archive authorize allowed). The component map of #192 names tools/lint/ with the component server, because make sql-visibility checks the queries of the server module and runs only when that component is selected. |
The PR lane ports only the ticket and the integration fixes it needs; no behaviour of the ticket changes. |
| M1-70/13 |
2026-10-21 |
Port onto main after M1-67 and M1-68: M1-67 brought the same mutex of httpserver.SchemaValidator with its doc comment and its concurrency test, so the lock of M1-70/8 is main's and the test TestSchemaValidatorConcurrent of this ticket is not ported (INT-W42/0); the harness client keeps both tb (M1-67, G9) and apiToken; the Makefile and tools/pyproject.toml name sql-visibility and tools/lint next to signal-check and tools/signalcheck of M1-68. |
The PR lane ports only the ticket and the integration fixes it needs; no behaviour of either ticket changes. |