Skip to main content

Security & limits

Source sharing​

Live reviews send selected files' full before/after contents, commit identifiers, check status, and assertion text to the configured provider: TypeSafe by default. Check logs and environment credentials are not included in that payload. The provider's API key authenticates the HTTP request, and --endpoint overrides come only from the invoker, never from repository configuration.

Folder entries send every Git-visible file beneath them, including local untracked files that are not ignored. Only select source you are permitted to share. Never select files containing credentials or personal data. Sensitive-path rejection is an accident guard, not a secret scanner: a harmless filename can still contain secrets.

Inspect the outbound payload before sending private source:

node src/assertlens.ts --snapshot --dry-run

Dry run requires neither credentials nor network access, but its stdout contains source. Avoid saving sensitive payloads in shared logs.

Credentials and command isolation​

Set TYPESAFE_API_KEY through your secret manager or shell environment. Do not put it in configuration or source. The CLI does not load .env files.

Default commands run without a shell inside Bubblewrap for at most two minutes. AssertLens clears the child environment, provides a private home and temporary directory, and restores only a fixed operational environment. Service tokens never enter the sandbox.

Each command receives a writable disposable workspace containing Git-visible files. Local staging includes all tracked files even when ignore rules match, plus untracked files that are not ignored; --head uses the exact committed tree. The original repository, .git, untracked ignored files such as .env, host home, and runtime sockets are not mounted.

Runtime tooling is exposed read-only from existing system roots: /usr, /bin, /sbin, /lib, /lib64, /nix/store, /run/current-system/sw, and /opt. Network is disabled by default; --sandbox-network explicitly shares host networking.

Resource denial remains possible

Bubblewrap isolates files, environment, process visibility, and network access, but AssertLens sets no memory, disk, or fork/process-count quotas. Untrusted code can still cause denial-of-service before the timeout. Run high-risk code on a disposable host with external resource limits.

--no-sandbox bypasses this boundary, runs in the original local repository, and prints a warning. It removes TYPESAFE_API_KEY, GITHUB_TOKEN, and GH_TOKEN, but can still read other files, credentials, and network resources. Use it only for trusted local code; it is incompatible with --head.

For untrusted PR source, use trusted base tooling with --head REF -- command. AssertLens reads Git objects without checking PR source out on the host, materializes the committed tree, then executes it in Bubblewrap. The supplied GitHub workflows follow this boundary.

Scope and resource limits​

ResourceLimit
Selected files1–20 unique literal repository-relative files or folders per list
Files per scopeAt most 50 after folder expansion
Named assertions1–20
Assertion textNonblank, at most 1,000 characters
Request token budgetModel context: jev-1.13 allows 32k tokens for state plus the longest question and 64k for state plus all questions, estimated as bytes ÷ 3
Configuration, response, and individual source reads64,000 bytes each
Executable checkTwo minutes
Jev requestOne per distinct scope, sent sequentially; 30 seconds each; no automatic retries

Regular UTF-8 source files only: no symlinks, binaries, traversal, globs, or submodules. Git path names used for sandbox staging must also be valid UTF-8; non-UTF-8 Git paths are rejected. Oversized input fails instead of silently dropping context. The token estimate is conservative but not exact; server context-limit errors also make a review unavailable. Aliases such as jev-latest and unknown models use the jev-1.13 budget.

No dependency discovery occurs. Omitted source and tests remain outside the review scope, even when selected files import them.

Unavailable is not passed​

Missing credentials, malformed or missing answers, invalid probabilities, network failures, and a changed source snapshot during checks cannot produce a completed review. A selected file missing in both revisions also fails validation.

With no command, checks are not_run, not passed. Without --snapshot, scopes with only unchanged files are skipped; review is not_run (exit 3) when every scope is unchanged. The CLI's exit codes distinguish unavailable review from failed executable checks.

Source recollection is not a filesystem lock. Sandboxed command mutations are contained in the disposable workspace, but concurrent host edits can still change the reviewed working tree; AssertLens detects selected-file differences and makes the review unavailable.

Model judgments are advisory​

Jev chooses supported, contradicted, or insufficient for each claim. Reports retain raw choice, confidence, and all three probabilities. Insufficient evidence or confidence below 0.8 becomes needs_review.

The threshold is an uncalibrated advisory starting point. Neither model confidence nor passing tests proves general correctness. A completed review with contradictions still exits 0; there is no model-based merge-blocking mode.

The test suite uses mocked API responses and does not measure live Jev accuracy. Before considering model-driven blocking, evaluate representative known-good and buggy changes and measure false positives, misses, and uncertainty.

API contract: TypeSafe API reference.