Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions adapters/exact_phrase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""PostgreSQL-backed content-free exact-phrase candidate discovery."""

from __future__ import annotations

from engine.runtime.content_io import exact_phrase_digest
from engine.runtime.contracts import Acquire
from engine.runtime.evidence import CandidateRef
from engine.runtime.materialized import (
MaterializedProjectionSession,
_discover_materialized_exact_phrase,
)


class PostgreSQLExactPhraseCandidateIndex:
"""Discover content-free candidates within one trusted Organization."""

def discover(
self,
request: Acquire,
projection_session: MaterializedProjectionSession,
) -> tuple[CandidateRef, ...]:
if type(request) is not Acquire:
raise TypeError("exact phrase discovery requires Acquire")
return _discover_materialized_exact_phrase(
projection_session,
exact_phrase_digest(request.need.query),
)
151 changes: 151 additions & 0 deletions adapters/file_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
"""Explicit host bindings for registered logical File roots."""

from __future__ import annotations

import os
import stat
from collections.abc import Mapping
from dataclasses import dataclass
from pathlib import Path
from types import MappingProxyType

from engine.control import FileImportPath, FileRootRef

MAX_CONFIGURED_FILE_BYTES = 64 * 1024 * 1024


@dataclass(frozen=True, slots=True)
class FileReadLimits:
"""Server-owned hard ceiling for one acquired File payload."""

max_file_bytes: int

def __post_init__(self) -> None:
if (
type(self.max_file_bytes) is not int
or not 1 <= self.max_file_bytes <= MAX_CONFIGURED_FILE_BYTES
):
raise ValueError("File byte ceiling must be a bounded positive integer")


@dataclass(frozen=True, slots=True)
class _AnchoredRoot:
display_path: Path
descriptor: int


def _open_anchored_directory(path: Path) -> tuple[Path, int]:
"""Open every absolute path component without following any symlink."""

absolute = Path(os.path.abspath(path))
flags = os.O_RDONLY | getattr(os, "O_DIRECTORY", 0)
no_follow = getattr(os, "O_NOFOLLOW", 0)
descriptor = os.open(absolute.anchor, flags | no_follow)
try:
for component in absolute.parts[1:]:
next_descriptor = os.open(
component,
flags | no_follow,
dir_fd=descriptor,
)
os.close(descriptor)
descriptor = next_descriptor
if not stat.S_ISDIR(os.fstat(descriptor).st_mode):
raise NotADirectoryError
return absolute, descriptor
except Exception:
os.close(descriptor)
raise


class FileRootRegistry:
"""Resolve a logical root and closed filename without discovering files."""

__slots__ = ("_limits", "_roots")

def __init__(
self,
roots: Mapping[FileRootRef, Path],
*,
limits: FileReadLimits,
) -> None:
if not isinstance(roots, Mapping) or not roots:
raise ValueError("File root registry requires explicit bindings")
if type(limits) is not FileReadLimits:
raise TypeError("File root registry requires FileReadLimits")
copied: dict[FileRootRef, _AnchoredRoot] = {}
try:
for root_ref, root_path in roots.items():
if type(root_ref) is not FileRootRef or not isinstance(
root_path, Path
):
raise TypeError(
"File root bindings require FileRootRef and Path"
)
try:
display_path, descriptor = _open_anchored_directory(root_path)
except OSError:
raise ValueError(
"File root must be an existing non-symlink directory"
) from None
copied[root_ref] = _AnchoredRoot(display_path, descriptor)
except Exception:
for root in copied.values():
os.close(root.descriptor)
raise
self._roots = MappingProxyType(copied)
self._limits = limits

def resolve(self, root_ref: FileRootRef, path: FileImportPath) -> Path:
if type(root_ref) is not FileRootRef or type(path) is not FileImportPath:
raise TypeError("File root resolution requires exact contracts")
anchored = self._roots.get(root_ref)
if anchored is None:
raise LookupError("File root is not configured")
target = anchored.display_path / path.value
if target.parent != anchored.display_path:
raise LookupError("File target is outside the configured root")
return target

def read(self, root_ref: FileRootRef, path: FileImportPath) -> bytes:
"""Read one regular file without following a final symlink."""

self.resolve(root_ref, path)
anchored = self._roots[root_ref]
flags = os.O_RDONLY | getattr(os, "O_NOFOLLOW", 0)
try:
descriptor = os.open(path.value, flags, dir_fd=anchored.descriptor)
except OSError:
raise LookupError(
"File target is not a regular configured-root file"
) from None
try:
metadata = os.fstat(descriptor)
if (
not stat.S_ISREG(metadata.st_mode)
or metadata.st_size > self._limits.max_file_bytes
):
raise LookupError(
"File target is not a regular configured-root file"
)
with os.fdopen(descriptor, "rb", closefd=False) as stream:
payload = stream.read(self._limits.max_file_bytes + 1)
if len(payload) > self._limits.max_file_bytes:
raise LookupError("File target exceeds the configured byte ceiling")
return payload
finally:
os.close(descriptor)

def close(self) -> None:
"""Release the server-owned directory capabilities."""

roots = self._roots
self._roots = MappingProxyType({})
for root in roots.values():
os.close(root.descriptor)

def __enter__(self) -> FileRootRegistry:
return self

def __exit__(self, *args: object) -> None:
self.close()
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
name: adr-0037-publish-first-file-through-exact-worker-lease
version: "1.0.0"
description: >
Activate one trusted Markdown File import through an exact durable WorkerLease,
atomic immutable publication, and a content-free exact-phrase CandidateIndex.
---

# 0037. Publish the first File through an exact WorkerLease

- Status: accepted
- Date: 2026-07-22
- Refines: ADR-0018, ADR-0029, ADR-0035, ADR-0036

## Context

Issue #23 is the first end-to-end Supply-to-Runtime tracer. It must turn one
registered File Source and one trusted Markdown filename into an authorized
`ContextPackage` without promoting the Issue #17 no-op carrier into an implicit
content authority. The worker needs filesystem access, while Control and Runtime
must remain unable to accept a host path or caller-authored tenant facts. Initial
publication also needs a Resource row before its immutable Revision can satisfy
the deferred active pointer.

## Decision

File Source registration remains the unavailable version-1 declaration from
Issue #21. A trusted `prepare_file_import` Control call validates one basename
ending in `.md`, revalidates the current audience Membership and registered File
import ServicePrincipal, creates an immutable version-2 SourceVersion declaring
only `fileSourceAccess` and `ingestionJobs` available, atomically switches the
Source active pointer, and creates one immutable acquisition plus one durable
job. Control stores only a logical root reference and relative filename; it never
opens the filesystem.

The version-2 WorkerLease preserves the version-1 no-op token bytes and binds
Organization, exact durable job, Source, receiver, workload
`supply.file-import`, audience `context-engine-worker`, operation `file.import`,
database-owned issue/expiry times, key version, and nonce. Redemption and
publication each revalidate those exact current row values, database time, and
the enabled ServicePrincipal. The content-free terminal failure transition has
the same checks, so expiry or receiver revocation cannot retain even a failed
state mutation. The worker receives no user impersonation authority.

The File adapter opens every component of a server-owned logical root as a
no-follow directory capability, then opens exactly one validated filename
relative to that retained descriptor. It accepts only a regular file below an
explicit server-owned byte ceiling. Bytes pass unchanged into the Issue #22
compiler. One successful compilation is published in one database
transaction as Resource, immutable Revision, immutable compilation snapshot,
one paragraph Fragment, mirrored Resource access, exact Membership body right,
content-free exact-phrase candidate, ordered `prepared -> indexed -> active`
events, active pointer, and completed job. Any failure rolls the entire effect
back; a post-redemption acquisition or compilation failure leaves only a
content-free terminal failed-job marker so it cannot remain runnable. The
reversible migration removes only Issue #23-owned rows and schema
before restoring the Issue #21 and Issue #17 constraints.

The exact-phrase index stores a SHA-256 query digest and lineage references, not
content. Its Runtime SELECT requires the complete current UserActor transaction
context and runs inside the same retained projection transaction used by the
Kernel. It does not truncate digest matches before authorization because doing
so could hide a later authorized candidate behind earlier denied candidates;
returned `CandidateRef` values remain untrusted discovery output.
Every candidate still crosses the sealed AuthorizationKernel and
`AuthorizedProjection` gates before content-bearing assembly. Cross-Organization
or scope-denied resolution returns the canonical empty package.

## Rationale

This is the smallest production-shaped tracer that exercises real acquisition,
durable job authority, immutable publication, retrieval, authorization,
provenance, and HTTP delivery. Logical roots keep deployment paths out of
contracts. A content-free deterministic index proves that retrieval is not
authorization. Atomic publication prevents Runtime from observing prepared or
indexed content before the active pointer and access rights agree.

## Consequences

- One explicitly prepared Markdown basename can be imported and resolved by an
exact phrase through the public HTTP seam.
- Direct worker table mutation remains unavailable; the shared definer role has
only operation-specific policies, grants, and functions.
- Directory discovery, watchers, symlinks, traversal, multiple files, update,
delete, hash no-op, retry/recovery, replacement, and approximate retrieval
remain unavailable.
- The complete WorkerLease contract is still not proven for Policy Epoch,
generation, outbox, or arbitrary Source operations.

## Revisit trigger

Revisit before accepting directory trees, links, remote files, repeat imports,
updates/deletes, checkpointing, recovery, approximate search, more compiler
shapes, or a broader ServiceActor operation set. Each expansion must retain
exact durable-job binding, server-owned roots, atomic immutable publication, and
the `CandidateRef -> AuthorizationKernel -> AuthorizedProjection` boundary.
14 changes: 14 additions & 0 deletions engine/control/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
)
from engine.control.contracts import (
FILE_CAPABILITY_MANIFEST,
FILE_IMPORT_CAPABILITY_MANIFEST,
CapabilityStatus,
FileCapabilityManifest,
FileRootRef,
Expand All @@ -26,10 +27,18 @@
SourceResourceKind,
SourceVersion,
)
from engine.control.file_imports import (
FileImportAudience,
FileImportPath,
FileImportReceiver,
PreparedFileImport,
PrepareFileImport,
)
from engine.control.module import ContextControl, ControlStorePort

__all__ = [
"FILE_CAPABILITY_MANIFEST",
"FILE_IMPORT_CAPABILITY_MANIFEST",
"CapabilityStatus",
"ContextControl",
"ControlOperation",
Expand All @@ -39,8 +48,13 @@
"ControlOperatorAuthorityUnavailable",
"ControlStorePort",
"FileCapabilityManifest",
"FileImportAudience",
"FileImportPath",
"FileImportReceiver",
"FileRootRef",
"RegisterFileSource",
"PrepareFileImport",
"PreparedFileImport",
"SourceAclEvidenceMode",
"SourceControlUnavailable",
"SourceContentKind",
Expand Down
1 change: 1 addition & 0 deletions engine/control/authority.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@


class ControlOperation(StrEnum):
IMPORT_FILE = "import_file"
REGISTER_SOURCE = "register_source"
READ_SOURCE = "read_source"

Expand Down
Loading
Loading