-
Notifications
You must be signed in to change notification settings - Fork 0
FILE_INGRESS
Every user-selected input is checked by one typed policy before decoding,
opening SQLite, invoking a provider over the network, or creating an output.
The same policy is used by one-shot commands, the interactive console, and
application services. Failures use stable coded errors, exit with status 2,
disclose neither the input path nor its contents, and leave existing outputs
unchanged.
All sizes are source bytes, not decoded character counts. A physical-line limit
includes its newline bytes. records means level-zero records for GEDCOM, the
aggregate rows across all inspected RootsMagic tables (with the same limit
also applied to each table), and physical lines for other text formats.
items is the aggregate number of JSON/TOML collection members, or lines in
one GEDCOM logical record.
| Input class | Total bytes | Physical line bytes | Records/rows | Logical record bytes | Nesting | Collection items |
|---|---|---|---|---|---|---|
config |
1,048,576 | 65,536 | 20,000 | — | 16 | 20,000 |
gedcom |
536,870,912 | 1,048,576 | 5,000,000 | 16,777,216 | 99 | 250,000 |
rootsmagic |
8,589,934,592 | — | 5,000,000 aggregate and per table | 16,777,216 | — | 50,000 |
ocr |
5,000,000 | 1,048,576 | 100,000 | — | — | — |
manifest |
33,554,432 | 1,048,576 | 500,000 | — | 64 | 2,000,000 |
json_schema |
2,097,152 | 262,144 | 50,000 | — | 64 | 100,000 |
prompt_body |
1,048,576 | 262,144 | 50,000 | — | — | — |
GEDCOM remains a streaming input: only one logical record is accumulated by the parser at a time. RootsMagic is opened read-only only after its regular-file and byte checks pass. Schema and table cursors are consumed incrementally; each row is validated before the next row is fetched. SQLite's connection-level length limit rejects very large text/blob values before Python materializes them, while the logical-row check enforces the exact configured byte budget. JSON and TOML documents are byte- and line-bounded before parsing, then checked for nesting and collection size. JSON containers and TOML arrays/inline tables are also scanned before recursive parser work, and parser recursion is mapped to the same stable nesting-limit failure. GEDCOM accepts UTF-8 and BOM-declared UTF-16; config, manifest, schema, OCR, and prompt-body text accept UTF-8 only. An accepted byte-order mark is counted in the total input budget and in the first physical-line and logical-record budgets; it is never a free prefix outside the configured limits.
Multi-pass GEDCOM synchronization and RootsMagic query/export bind every parse,
hash, database read, provider preflight, and copy to the identity first verified
for that operation. The identity includes device, inode, size, modification
time, and filesystem change time; a SHA-256 fingerprint is carried through
publication. Replacing a file with a same-size file, restoring its modification
time, or changing it between validation and a later pass is therefore rejected.
The captured identity also binds the filesystem link count. RootsMagic inputs
must have exactly one link because a hard-link alias could hide SQLite
transaction sidecars under a different pathname; create a standalone stable
backup instead of querying an aliased database.
Each configured RootsMagic directory is also bound to its filesystem identity
when the service is created. Source opens and sidecar checks traverse from that
verified directory capability, rather than reopening an unchecked absolute
pathname. Replacing a parent with a symbolic link, junction, or different
directory therefore fails as FILE_INPUT_CHANGED before database bytes,
schema, or rows can reach SQLite, an export, or a provider.
RootsMagic operations accept a valid main database plus -wal, and verify a
matching -shm when present, only after descriptor-bound fingerprints, a
verified copy into a process-owned directory, a full WAL checkpoint, and
SQLite backup consolidation. When SHM is absent, SQLite reconstructs it only in
owned staging; the source is unchanged. The original database and sidecars are
never opened by SQLite. The composite source identity is rechecked after every
copy and consolidation step. A busy, malformed, replaced, symbolic-link, or
non-regular sidecar fails closed with ROOTSMAGIC_WAL_ACTIVE or
FILE_INPUT_CHANGED. Any rollback -journal, or an -shm without a WAL, is
rejected. Closing RootsMagic or using a stable backup remains the most reliable
operational choice, but a verified WAL generation is supported.
Export reports identify whether the immutable SQLite snapshot came from a
standalone main database or a verified main plus WAL generation. Raw
sidecar paths and hashes remain deliberately absent from the user-facing
report; the composite fingerprint stays internal so local filesystem metadata
is not disclosed.
The RootsMagic adversarial acceptance matrix is:
| Input condition | Result and invariant |
|---|---|
| Stable standalone database; valid WAL with matching SHM when present | Accepted from a verified process-owned immutable snapshot; source bytes, schema, mode, and modification time remain unchanged. |
| Rollback journal; SHM without WAL; malformed, busy, replaced, symbolic-link, or non-regular sidecar | Rejected with a stable sanitized error before rows, export content, or provider traffic. |
| Corrupt/truncated SQLite or malformed/hostile schema identifiers | Rejected or safely quoted with no source mutation and no raw SQLite/path disclosure. |
| Excessive tables, columns, aggregate rows, or per-table rows | Rejected incrementally at the configured collection/record boundary. |
| Oversized text/blob, embedded NUL text, or invalid UTF-8 text | Rejected before publication; no output/report partials or temporary artifacts remain. |
| Duplicate/missing person identifiers, orphan links, self-links, or relationship cycles | Rejected when identity is ambiguous; otherwise exported deterministically without inventing relationships. |
Natural-language RootsMagic queries encode the inspected schema and question as
one deterministic JSON data payload beneath a separate fixed system policy.
The complete UTF-8 payload must fit file_ingress.prompt_body.max_bytes before
provider execution. An excess fails locally as
ROOTSMAGIC_SCHEMA_PROMPT_TOO_LARGE with exit code 2 and sanitized limit
details; no schema values, question text, or provider request are emitted.
Overrides belong only in the normal non-secret config.toml boundary. No
environment variable is consulted for file-ingress limits. Omitted fields keep
their defaults. Values must be positive integers; physical-line limits must
also fit the platform's safe streaming-read size. Unknown sections, keys, and
wrong semantic types are rejected before configuration creates or changes any
directory.
[file_ingress.gedcom]
max_bytes = 268435456
max_line_bytes = 524288
max_records = 2500000
max_record_bytes = 8388608
max_nesting = 99
max_collection_items = 125000
[file_ingress.rootsmagic]
max_bytes = 4294967296
max_records = 1000000
max_record_bytes = 8388608
max_collection_items = 25000
[file_ingress.prompt_body]
max_bytes = 524288
max_line_bytes = 131072
max_records = 25000The configuration file itself always uses the compiled config defaults. It
cannot raise its own read budget. An omitted default config may be absent during
first-run initialization; a path supplied with --config must already be a
valid bounded regular file and is never created implicitly. Environment
fallback paths are resolved only when the selected configuration does not
override them, and an explicit --config never consults the default
configuration-directory fallback.
The policy rejects missing or unreadable inputs, directories, symbolic links,
FIFOs, devices, filesystems that do not expose a positive inode identifier,
known compressed/archive containers, invalid Unicode, invalid JSON, and any
exceeded byte, line, record, row, nesting, or collection limit.
User path expansion, absolute-path conversion, and canonical resolution pass
through the same sanitized boundary; a failed user lookup or path resolution
reports FILE_INPUT_UNREADABLE without disclosing the supplied spelling.
RootsMagic export and report destinations use that boundary too, so application
services, one-shot commands, and background console jobs preserve the same
typed error instead of leaking a runtime path-expansion failure.
NUL characters are rejected both as literal input bytes and after JSON or TOML
escape decoding, including in mapping keys.
It captures device, inode, size, modification time, and filesystem change time
before consumption and checks them again after the read, so replacement,
growth, truncation, or in-place modification fails as FILE_INPUT_CHANGED.
The inode identifier must be positive; a device identifier of zero remains
supported because Windows may legitimately report it. A filesystem without a
reliable inode fails as FILE_INPUT_UNREADABLE before any file bytes are
consumed.
Every report destination is checked against immutable inputs and its primary output by canonical path and filesystem identity. Symlink, hard-link, and alternate-spelling aliases are rejected before publication. Casefold- or Unicode-normalization-equivalent destination names are conservatively rejected on every platform so the same invocation remains safe when moved to a case-insensitive volume. Related primary and report artifacts are staged together; existing targets remain recoverable until every rename and final source-fingerprint check succeeds. Any second artifact or late validation failure restores both prior targets and removes publication temporaries. Publication is a rollback-capable logical transaction, not a promise of continuous old-or-new visibility to concurrent readers. On platforms without a portable multi-file exchange primitive, replacing an existing target can briefly make that target absent while its recoverable backup is installed or restored. A successful return means every published artifact has been reverified and the destination directories have been flushed where the platform exposes that durability operation. Windows does not expose a supported equivalent for flushing a directory handle after a namespace rename. Candidate file contents are flushed before publication, but crash-durability of the final Windows directory entry remains subject to the filesystem and operating system.
Stable file-ingress codes are:
FILE_INPUT_UNREADABLEFILE_INPUT_NOT_REGULARFILE_ARCHIVE_UNSUPPORTEDFILE_INPUT_TOO_LARGEFILE_LINE_TOO_LONGFILE_RECORD_LIMIT_EXCEEDEDFILE_RECORD_TOO_LARGEFILE_NESTING_LIMIT_EXCEEDEDFILE_COLLECTION_LIMIT_EXCEEDEDFILE_INPUT_CHANGEDFILE_INPUT_IOFILE_ENCODING_INVALIDFILE_NUL_BYTE_UNSUPPORTEDFILE_INPUT_EMPTYFILE_FORMAT_INVALIDFILE_JSON_INVALIDFILE_JSON_TYPE_INVALID
Compressed and archive inputs are not expanded by AncestryLLM. Extract them with a trusted local tool, inspect the resulting regular file, and pass that file directly. Rejection occurs before any provider network invocation, so it cannot make a network request even when provider credentials are present.
- Home
- CLI reference
- Interactive console guide
- Architecture ownership and dependency contracts
- Bounded file ingress
- Versioning and compatibility
- Continuous integration
- Release runbook
- Encrypted backup and recovery
- First-run storage diagnostics
- GEDCOM compatibility and release checks
- Built-in module authoring
- Privacy and consent
- Provider guide
- Local LLM benchmarks
- Local-first retrieval evaluation
- Wiki synchronization
- Wiki operations and recovery
- Security response checklist
- Electron and FastAPI desktop ADR
- Data-flow threat model and control matrix