Skip to content

relay: reject a zero frame-memory budget or per-IP cap in the validator #996

Closed

Description

@chappie-daemon

#989 made frameMemoryBudgetBytes and maxConnectionsPerIp settings keys, but gave 0 a new meaning: use the compiled default, reported as a distinct verdict rather than a violation (BoundRefusal::Zero, in_range's value > 0 floor, config_defaults.rs::a_zero_setting_falls_back_to_the_compiled_default).

That is the wrong answer, and the record already says so. ADR 0008:331 — "A zero budget or a zero cap is a literal the operator wrote" — is the sentence #989 cites. A 0 meaning default contradicts it and adds a fourth meaning to a value that is already disabled in limits.client.subscription (CONFIGURATION.md:161-163) and invalid in targetEventsPerSecond (validate.rs:100). These two bounds belong to neither: a zero budget or a zero cap is a relay that cannot serve.

What it needs

  1. from_settings: drop the bytes > 0 guard — a present value is used as written; None still means the compiled default.
  2. validate_document: two issues in the existing shape, matching validate.rs:94/:100 —
    Issue::new("network.frameMemoryBudgetBytes", "frameMemoryBudgetBytes must be greater than 0") and
    Issue::new("limits.connection.maxConnectionsPerIp", "maxConnectionsPerIp must be greater than 0").
  3. Reverse the test: 0 on each key produces its issue, rather than the default.
  4. The defaults-document comments above each key and both CONFIGURATION.md rows state the unit and that 0 is rejected.
  5. ADR 0008's ## What 0 means rewritten to this answer, quoting :331 and naming the two existing idioms — after the last code commit.

Why rejection: its failure is loud and early — the app checks the file and names the key, and --check exits non-zero. A fallback turns a typo into a relay that silently budgets 256 MiB, and the operator's only clue is a reading of a file they did not write.

Found by the operator in job 017's review; 017 shipped the opposite because the policy was asked in the spec and the answer arrived after the build.

Activity

  1. added
    rewritenostream 4.0 Rust/LMDB rewrite
    rustRust implementation work
    factoryBuilt by the software factory
    on Oct 25, 2026
  2. chappie-daemon commented on Nov 1, 2026

    @chappie-daemon
    CollaboratorAuthor

    Closed by 959cfa42 (PR #997), verified in the tree: git merge-base --is-ancestor 959cfa42 rewrite/main returns 0.

    Closed by hand rather than by the PR's Closes keyword: GitHub only auto-closes on merge when the pull request targets the repository's default branch, and cameri/nostream's default is main while this PR targeted rewrite/main. The keyword was decoration and the issue stayed open after the merge.

    Every factory job landing on the rewrite now closes its own issue with gh issue close <n> --reason completed and reads the state back as CLOSED, never trusting the PR body.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    factoryBuilt by the software factoryrewritenostream 4.0 Rust/LMDB rewriterustRust implementation work

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions