Skip to content

Release 0.6.17 - #44

Merged
O6lvl4 merged 15 commits into
mainfrom
develop
Oct 3, 2026
Merged

O6lvl4 merged 15 commits into
mainfrom
develop

Conversation

@O6lvl4

@O6lvl4 O6lvl4 commented Oct 3, 2026

Copy link
Copy Markdown
Contributor
  • Add a job API for evaluating porta as a WASM job runtime: porta job-check, job-run, job-serve. An operator policy pins modules by SHA-256 and sets grants and ceilings; each job runs in its own worker process under fuel, memory, deadline and output limits, by default also under porta's OS sandbox; every run gets a record (run id, policy label and digest, module and job digests, times, outcome, stop reason) and a line in events.jsonl
  • Evaluation image (Dockerfile), sample job and examples/enterprise/evaluate.py; cloud templates for ECS, Cloud Run, Container Apps and Cloudflare Containers (written, not deployed); threat model, compatibility table, operations, distribution and gap list in docs/enterprise/
  • scripts/job_integration.py (85 checks) runs in CI on Linux and macOS
  • Includes the credential broker, the portable static Linux binary and the other develop changes since 0.6.16

🤖 Generated with Claude Code

O6lvl4 and others added 15 commits September 27, 2026 22:55
The child's environment starts empty, and the caller's TMPDIR stays out on
purpose: on macOS it is the per-user /var/folders/.../T, which the profile
keeps closed. But a program with no TMPDIR asks the OS instead, and Rust's
std::env::temp_dir on macOS gets that same closed directory. So every
temporary file an Almide or Rust program made under porta was refused.
golemide's solve failed all six attempts that way inside onogoro.

The child now gets TMPDIR=/tmp, the temporary directory the run is granted,
on both platforms; -e TMPDIR=... still overrides it. explain lists it, and
an integration test checks both.

Closes #38

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Linux release was linked on the Ubuntu 24.04 runner, so it asked for
glibc 2.39 and libssl.so.3 and did not start on Debian 12, Ubuntu 22.04
or the python:*-slim images: most containers an agent runs in.

- reqwest without its default features: TLS is rustls only
- scripts/build-linux.sh builds in Debian bullseye, with the pinned
  Almide built from its tag there, and refuses a result past glibc 2.31
  or one linking OpenSSL
- release.yml builds Linux with it; the integration suite still runs
  the result on the runner
- ci.yml checks that no OpenSSL is linked on Linux
- README: the glibc floor

Closes #35

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…older

On Docker Desktop, a macOS folder bind-mounted into a container is a
fakeowner filesystem, and under Landlock a command there can create a
file but not write to it. The ruleset grants the mount; the kernel
refuses the open anyway, leaving empty files and a bare Permission
denied. porta now reads /proc/self/mountinfo and, when a writable -v
lies on fakeowner, says so once, with what to use instead.

docs/enforcement.md describes the limit.

Closes #36

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Tell the child its temporary directory is /tmp
Ship a Linux binary that starts on glibc 2.31 and needs no libssl
Say before the run when a writable mount is a Docker Desktop shared folder
`--credential NAME=HOST[/path]` and `[[credentials]]` hand the command a
placeholder, porta-cred-NAME-<random>, instead of the key. The real value,
read from porta's environment, stays in porta. A credential turns the
proxy on; for a bound host the proxy terminates the command's TLS with a
certificate from a CA made for this run, puts the value where the
placeholder is (request line, query, headers), and sends the request on
over its own TLS connection verified against the webpki roots. The same
placeholder on a path it is not bound to is refused with 403 before
anything is sent. Substitutions and refusals are recorded by name,
never by value. Hosts no credential names are tunnelled as before.

The command trusts the CA through SSL_CERT_FILE, REQUESTS_CA_BUNDLE,
CURL_CA_BUNDLE and GIT_SSL_CAINFO (system roots plus the CA) and
NODE_EXTRA_CA_CERTS (the CA alone). The CA lives for a week, in memory;
its files are removed when the proxy stops.

rustls and rcgen on ring, the provider reqwest already builds: no second
crypto library and no OpenSSL. PORTA_TEST_UPSTREAM(_CA) lets the
integration suite send a CONNECT to a local server; it is read from
porta's own environment.

Closes #37

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
CI's code-quality floor (90) failed at 89: credential_broker.rs was one
488-line file with a deeply nested body copier and five-parameter
functions, http_proxy.rs had passed 300 lines, and so had cli.almd.

- credential_broker.rs keeps the credentials and where each may go;
  credential_broker/tls.rs makes the run's CA, its leaves, the trust
  bundle and the upstream verifier; credential_broker/exchange.rs carries
  one intercepted request; the unit tests move to credential_broker/tests.rs.
  A Target (host, port) replaces the separate arguments.
- The tunnel and wt_is_host_allowed move beside the dial in
  proxy_egress.rs; the proxy's setup with credentials is one function.
- The TOML quoting helpers move to util.almd; --credential parsing and the
  saved [[credentials]] tables to proxy.almd.

No behaviour change: 163 Almide tests, 5 broker unit tests, the whole
integration suite and escapes.py pass as before; codopsy grades 90 (A).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Credentials as placeholders, put on by the proxy for bound hosts only
…ry (#43)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
porta job-check, job-run and job-serve take a WASM job and an operator
policy, run each job in its own worker process under fuel, memory,
deadline and output limits with only the granted directories, and write a
run record: run id, policy label and digest, module digest, times, outcome
and stop reason. With os_sandbox = "required" every worker also runs
under porta run. A container image, cloud templates (not deployed), the
threat model, compatibility table and gap list are in docs/enterprise.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…me escape

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fusing every job

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aks rustls only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@O6lvl4
O6lvl4 merged commit e909f53 into main Oct 3, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant