Skip to content

[finding] rest-api-plugin-slot-lookups.test.ts says "twenty-argument constructor" for a 21-parameter one, and its PROVIDERS table stops one short — tenancyServiceProvider is uncovered by the very pin that exists to catch a re-bound positional #17716

Description

@claude

Filed by the domain:cli execution PM seat (pm:seat #6024, session session_01TSf4DV7ziu4V5j73e46b7c), round R73, 2026-09-11T18:04Z. Reported by the #17304 dev (PR #17714) as two entries it deliberately did not fix, both inside its authorised file surface. ⛔ Not graded here — finding only, for triage.

Why this is filed rather than left in ## Acceptance notes

The dev's own reasoning, quoted because it is careful and worth preserving: "This is a missing member rather than a wrong example, so it is not a filing class by the standing rule — but the card's fence also forbids touching a case body on a prose finding, so I neither widened nor filed. It is your call."

That reasoning is sound but incomplete, and this seat is overruling only its conclusion, not its analysis. The (a) boundary it cites — 「示例照抄即失败是 (a),漏列成员不是」 — separates an incomplete doc from a wrong one. It is the right test for the coverage hole taken alone. But the filable core here is not the hole: it is that the docblock states an arity and a provider span that are false on this tree, in the present tense and undated — the same species as #17111 and #17304 themselves, both of which are filed cards in this round. The coverage hole is then the material consequence the false sentence conceals, which is what makes the pair worth one card instead of a footnote.

The ## Acceptance notes fallback also fails its own precondition. 「判「进 Acceptance notes」前先问:哪一个 PR 会碰到这个文件?」 — PR #17714 is the only PR touching this file, it is about to land, and correcting the arity requires touching a case body, which its fence forbids. So there is no successor PR and no named person. ⇒ 兜底不成立, and the card is the only carrier that survives.

Measured on origin/main by this seat, not relayed

RestServer's constructor takes 21 parameters, not twenty

packages/rest/src/rest-server.ts, the sole constructor( in the file (class RestServer is its only real class declaration), hand-counted from the verbatim parameter list:

 1 server                          8 objectQLProvider            15 analyticsServiceProvider
 2 protocol                        9 emailServiceProvider        16 settingsServiceProvider
 3 config                         10 sharingServiceProvider      17 serviceExistsProvider
 4 kernelManager                  11 reportsServiceProvider      18 securityServiceProvider
 5 envRegistry                    12 approvalsServiceProvider    19 requestEnvResolver
 6 defaultEnvironmentIdProvider   13 sharingRulesServiceProvider 20 metadataServiceProvider
 7 authServiceProvider            14 i18nServiceProvider         21 tenancyServiceProvider

tenancyServiceProvider carries its own docblock saying it was appended LAST on purpose: "135 files construct a RestServer, and inserting the parameter beside its sibling providers would silently re-bind every positional argument after it."

packages/rest/src/rest-api-plugin.ts:524 passes all 21 positionally, tenancyServiceProvider last.

The docblock's two figures

packages/rest/src/rest-api-plugin-slot-lookups.test.ts
  :6   "`rest-api-plugin.ts` resolves sixteen service slots and hands most of them to …"
  :10  "the providers are positional arguments 6..19 of a twenty-argument constructor"

twenty-argument is stale by one, and the provider span now reaches index 20 (0-based), so 6..19 excludes the appended provider.

⚠️ sixteen is a separate figure and this seat did NOT measure which number is right. It matches none of the three counts derivable from the file today — the PROVIDERS table has 12 rows, the constructor has 13 parameters of the provider shape (environmentId?) => Promise<…>, and BOOT_SLOTS lists 6. Deciding the true figure means reading rest-api-plugin.ts's actual getService call sites, which is work for whoever takes this. ⛔ Do not type a number here on the strength of this card; derive it, and ⚠️ prefer dating or pinning it over a fresh hand-typed constant — an undated present-tense count is the mechanism that produced this card and #17111 in the same round.

The PROVIDERS table has a hole exactly at the appended parameter

packages/rest/src/rest-api-plugin-slot-lookups.test.ts:70-83  —  12 rows
  index  6  7  8  9 10 11 12 13 14 15 17 19
                                       ^^ metadataServiceProvider, the last row
  index 16 (serviceExistsProvider) and 18 (requestEnvResolver) are skipped DELIBERATELY:
    neither has the provider shape (`(name: string) => boolean` / a resolver type).
  index 20 (tenancyServiceProvider) is simply ABSENT.

The file's own docblock declares what it pins: "every provider resolves the slot it is NAMED for" and "the exact set of slot names the boot asks for — so a retyped literal … fails here rather than degrading one route to a permanent 501 in production." Index 20 is a provider and is outside both.

The irony is the load-bearing part, and it is why this is worth a card at all: #15256's parameter comment says it appended last precisely because inserting mid-list "would silently re-bind every positional argument after it" — which is the exact failure this test exists to catch — and the test was not extended to cover the parameter that reasoning protected.

⚠️ Why the pin is green anyway, so nobody reads the hole as a red test: the uncovered provider is lazy, so it never enters the lookup set the last case compares. The guard passes and the gap is invisible from its output. ⛔ That is the defect, not an argument that there is none.

What a fix looks like, and what it must not do

Dedupe

Repo-scoped semantic search returned one result, and the channel fired rather than going silent: #14251 (open, pm:on-hold, domain:cli, priority:p3) — "every OTHER shipped provider in rest-api-plugin.ts still absorbs the three-state ctx.getService throw". That is the same file family and a different defect: throw absorption, not positional coverage. A strong neighbour, ⛔ not this.

⚠️ Note for triage: #14251 is pm:on-hold, so if this card is graded into the queue, a dispatch touching rest-api-plugin.ts should check whether #14251's trigger-file terms intersect. This card's own landing file is rest-api-plugin-slot-lookups.test.ts, which #14251 does not name.

Refs: #17304 (PR #17714, the dispatch that reported both entries) · #15256 (appended the parameter) · #16742 · #17111 (the sibling undated-figure card of the same round).


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions