Notarizing documentation
Limits
Developer preview. Not yet production ready. This page is rendered from docs/limits.md of the Notarizing repository at revision d23579e737f9d1e16e07b3c6b21a51282d64027e. It describes the behavior of that revision.
Contents
This page lists the limits that a user can meet, with their values and their source in the
code. Every limit is fixed in this build unless the table names a flag. A command that meets a
limit refuses the input with too_large or invalid_input, or it returns a partial result
that says what it omits. Notarizing never cuts an input in silence.
Section numbers name sections of
n0-decisions.md. Paths are
below internal/.
Workspace storage
| Limit | Value | Source |
|---|---|---|
| Retained report and artifact bytes of a workspace (each digest counted once) | 1 GiB | application.DefaultMaxWorkspaceEvidenceBytes, section 15 |
| Retained snapshot file bytes and target documents of a workspace | 1 GiB | application.DefaultMaxWorkspaceSourceBytes, section 19 |
| Imports that stage bytes at the same time | 2 | application.DefaultMaxConcurrentImports |
| SQLite busy timeout | 5 s | sqlitestore.DefaultBusyTimeout |
An import above a storage cap fails with too_large and stores nothing. Free space with
retention preview and retention apply (at most 10,000 receipts for each plan,
application.MaxRetentionReceipts).
Source import
| Limit | Value | Source |
|---|---|---|
| OpenSpec files read for one change | 2,000 | adapters/openspec.DefaultMaxFiles |
| Size of one OpenSpec file | 1 MiB | adapters/openspec.DefaultMaxFileBytes |
| Total OpenSpec bytes of one snapshot | 32 MiB | adapters/openspec.DefaultMaxTotalBytes |
| Git tree entries listed for one snapshot | 10,000 | adapters/git.DefaultMaxEntries |
| Time of one Git read | 60 s | adapters/git.DefaultTimeout |
Locator (--at) length | 255 bytes | adapters/git.MaxLocatorBytes |
| Requirement or declaration blocks in one file | 2,000 | adapters/openspec maxBlocksPerFile |
| Requirements in one target | 20,000 | maxRequirements |
| Declared nodes in one target | 20,000 | maxNodes |
| Declared edges in one target | 200,000 | maxEdges |
| Scenarios in one requirement block | 500 | maxScenariosPerBlock |
| Link items in one requirement block | 2,000 | maxLinksPerBlock |
| Extractor diagnostics of one target | 10,000 | maxDiagnostics |
| Premise group nesting | 16 levels | domain.MaxGroupNesting, section 7.2 |
| Identifier length | 128 characters | ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$, section 7.2 |
Changes listed by change list --at | 5,000 | adapters/openspec.MaxListedChanges |
A block, node or edge limit is a fatal diagnostic: the import stores a target_error target.
See Writing specifications.
Evidence import
| Limit | Value | Source |
|---|---|---|
| Report size | 256 KiB | adapters/reports.DefaultMaxReportBytes |
| JSON nesting of a report | 64 | adapters/reports.DefaultMaxDepth |
| Artifacts of one report | 64 | adapters/reports.DefaultMaxArtifacts |
| Size of one artifact | 16 MiB | adapters/reports.DefaultMaxArtifactBytes |
| Report and artifacts together | 64 MiB | adapters/reports.DefaultMaxPackageBytes |
| Search indexes rebuilt after one import command | 16 | cli.maxIndexRefresh, section 32.2 |
Reports for one evidence import command | 256 | cli.maxBatchReports, section 61.3 |
| Input file read by the CLI (bindings, policy and other JSON files) | 16 MiB | cli.MaxInputFileBytes |
A larger report fails with, for example,
too_large: report: invalid JSON at byte 262144: input is longer than 262144 bytes.
--no-index skips the index rebuild. Then run search index once at the end.
The producer gotestreport reads at most 16 MiB of go test -json output, 256 checks and 4,096
tests (examples/producers/gotestreport/main.go).
Bindings, policy and assessment
| Limit | Value | Source |
|---|---|---|
| Bindings assessed for one requirement revision | 1,000 | policy.MaxBindings |
| Required configurations of one binding | 32 | policy.MaxConfigurations |
| Receipts assessed for one requirement | 20,000 | policy.MaxReceipts |
| Reviewed supersessions | 10,000 | policy.MaxSupersessions |
| Receipts listed in one assessment row | 64 | application.MaxListedReceipts |
Review
| Limit | Value | Source |
|---|---|---|
| Review grant time to live | 1 minute to 8 hours, whole seconds | web/session.MinGrantTTL, review.MaxGrantTTL, http-api.md section 2.2 |
Browser sessions of one serve | 64; a new session ends the least recently used one | web/session.DefaultMaxSessions, section 23 |
| Failed viewer secret attempts | 5 each minute | web.MaxBootstrapFailures |
| Review events of one target | 10,000 | application.MaxReviewEventsPerTarget, section 24 |
| Review command body | 256 KiB | http-api.md section 2 |
| Rationale | 8,000 characters | review-command schema |
| Wording draft (replacement block) | 32,000 characters | review-command schema |
| Actor label | 64 characters | application.MaxActorLabelRunes |
| Source file of a review patch | 1 MiB | review.MaxPatchSourceBytes |
| Wording drafts in one patch | 32 | review.MaxPatchEdits |
A grant outside its range fails with --ttl must be whole seconds from 1m to 8h.
Browser views
| Limit | Value | Source |
|---|---|---|
| Requirements in the Review list | 1,000 | webapi.maxReviewRequirements |
| Assumptions, premise groups, questions, diagnostics in Review | 1,000, 500, 500, 500 | webapi/review.go |
| Explore graph nodes | 150 by default, at most 500 | graph.DefaultMaxNodes, session limits |
| Explore graph edges | 300 by default, at most 1,000 | graph.DefaultMaxEdges |
| Explore depth | 1 by default, at most 4 | graph.MaxDepth |
| Graph roots | 20 | graph.MaxRoots |
| Compare rows | 1,000 | webapi.maxCompareRows |
| Search query | 2,048 bytes | search.MaxQueryBytes |
| Search results | 50 by default, at most 100 | webapi/search.go |
| Source excerpt | 1,000 characters | session limits |
| HTTP request bodies | 1 KiB session, 8 KiB search, 16 KiB export, 256 KiB review command | http-api.md section 2 |
A cut list sets truncated and the page says so. A graph view that does not fit gives a next
page. The CLI graph query has the same depth, node and edge ranges:
--depth must be 0 to 4, --max-nodes 1 to 500 and --max-edges 0 to 1000.
Exports and bundles
| Limit | Value | Source |
|---|---|---|
| Receipts in one bundle | 4,096 | application.MaxBundleReceipts, section 25.6 |
| Artifacts of one bundled receipt | 64 | section 25.6 |
| One bundle file and the manifest | 16 MiB each | section 25.6 |
| Bundle size | the evidence cap plus 64 MiB; at most 8 GiB | application.MaxBundleBytesCeiling, section 25.6 |
| Review events in one bundle | 10,000 | section 36.2 |
| Source target references in one bundle | 1,000 | section 25.6 |
| Graph or review export document | 8 MiB | export.MaxDocumentBytes |
| Requirements and assumptions in a review export | 10,000 each | export.MaxReviewRequirements |
MCP
| Limit | Value | Source |
|---|---|---|
| One tool response | 512 KiB | mcp.MaxResponseBytes, section 27.4 |
| Change report in MCP | 200 requirements, 16 rows each, 200 assumptions, 100 groups, 100 questions, 2,000 characters for each text | mcp/tools.go |
| Graph | 50 nodes and 100 edges by default; at most 150 nodes, 300 edges, depth 2 | mcp/tools.go |
| Search | 20 results by default, at most 50 | mcp/tools.go |
A larger answer is cut and says what it omits, or it fails with too_large.
Optional ka2a adapter
The adapter configuration has its own limits: handler_timeout 1 s to 10 m, drain_timeout at
most 5 m, 1 to 1,000 source bindings, and a report of at most 256 KiB with at most 16 inline
artifacts (section 29). See the operator guide.
Measured scale
The qualification runs of 2026-09-30 measured these values on a shared, contended 4-CPU host (measurements, soak, section 32.6). A number describes its run only. It is not a capacity figure, a service level or a performance claim.
| Measurement | At 10,000 receipts |
|---|---|
| Evidence import, p50 | 10.7 ms |
| Change review of the target, p50 | 1.1 s |
| Lexical search index build | 3.1 s |
| Search for a requirement ID, p50 | 48.8 ms |
| Bundle export of the 4,096-receipt limit | 0.8 s, 16 MiB |
The 30-minute soak imported 9,939 reports through the control API and sent 9,943 browser
queries with caps of 64 MiB. It purged 4 times and ended with an integrity check ok.
What is not measured
- More than 10,000 receipts in one workspace.
- A target near the source limits (20,000 requirements, 200,000 edges).
- Several reviewers on one
serveat the same time. - Hosts other than linux/amd64, and disks other than the local disk of the measurement host.
- The semantic search provider under load.
- The ka2a adapter under sustained load. Its tests check correctness, not throughput.