commit dbfd099b0cbfe99070f8b4172c0236f939d54901
parent 3e8182889c0af630b8d32d43baf7c326ddcfaa7e
Author: triesap <tyson@radroots.org>
Date: Fri, 14 Aug 2026 04:05:52 +0000
docs: enforce standalone iOS authority
- add capsule-local agent guidance for the current source boundary
- keep human specifications and qualification evidence parent-owned
- reject forbidden docs and workflow roots during package validation
- remove the duplicated lifecycle checklist after verifying its parent copy
Diffstat:
3 files changed, 118 insertions(+), 44 deletions(-)
diff --git a/AGENTS.md b/AGENTS.md
@@ -0,0 +1,110 @@
+# Radroots iOS app agent specification
+
+This file applies to the complete standalone iOS app repository. A closer
+`AGENTS.md` overrides it for its subtree.
+
+## Authority and repository boundary
+
+- This capsule owns the public iOS application, its Swift package, generated
+ Xcode project, Apple host lifecycle, app state and views, FFI installation
+ boundary, privacy manifest, public API snapshot, and standalone validation.
+- `radroots.lib.source-lock.v1.toml`, `Cargo.toml`, and
+ `RadrootsFFI/source.lock` must select the same exact remotely reachable public
+ lib revision and release version. `Package.swift`, both
+ `Package.resolved` files, and `project.yml` own exact Apple package inputs.
+- `RadrootsFFI/provenance.json`, `RadrootsFFI/api/**`, `api/**`, generated
+ project/source inputs, and the package locks are machine evidence. Do not
+ hand-edit generated bindings, XCFramework contents, provenance, project
+ output, or API snapshots.
+- Human specifications, decisions, migration history, runbooks, and
+ qualification evidence are parent-owned under `docs/oss/ios_app/**`. They
+ are absent from a standalone clone and must never become a build, test,
+ package, generation, or release input for this capsule.
+- `docs/**`, `.github/**`, and `.act/**` are forbidden tracked roots. Public
+ commands remain forge agnostic; cross-repository workflow proof belongs only
+ to the parent workspace's root `.act/**` surface.
+- Do not depend on non-public parent paths, non-public contracts, implicit
+ sibling checkouts, floating branches/tags, or unrecorded local artifacts.
+
+## Product and security boundaries
+
+- The app is an iOS client. It owns Apple presentation, lifecycle callbacks,
+ user-presence prompts, Keychain integration, foreground/background
+ scheduling, and translation between generated SDK DTOs and view state.
+- Canonical domain policy, signing protocol, relay semantics, durable engine
+ state, wire contracts, and generated FFI models remain owned by their public
+ producer packages. Do not fork them into Swift application models.
+- Keep identity secrets in the Apple credential boundary. Never log, snapshot,
+ serialize, fixture, or expose secret material, raw private event content,
+ credentials, tokens, private paths, or unsafe internal errors.
+- Background work is host-owned, explicit, bounded, cancelable, and recoverable
+ across app lifecycle changes. Do not add hidden workers, process-global
+ runtime ownership, implicit relays, or direct database authority.
+- Services-hardening generated changes must adopt the approved four coverage
+ states and three outcomes across Swift and FFI together. Do not retain
+ prototype evidence, receipt, outcome, or compatibility aliases.
+
+## Generated and project files
+
+- Change canonical producer contracts and generators before regenerating FFI
+ or SDK output. Inspect every generated diff and run freshness/API checks.
+- `scripts/generate-project.sh` owns `Radroots.xcodeproj`; edit `project.yml`
+ and canonical source inputs rather than hand-editing generated project data.
+- `RadrootsFFI/scripts/verify-installed-artifacts.sh` must reject missing,
+ stale, mismatched, or unproven FFI installations before Swift/Xcode work.
+- Keep SwiftPM and Xcode workspace resolved revisions synchronized. Never allow
+ automatic dependency updates to select release inputs.
+- Repository scripts must keep Xcode derived data and source/package caches,
+ SwiftPM scratch/cache output, and Cargo target output under extbuild-owned
+ paths. `RadrootsFFI/.build/out/**` and `RadrootsFFI/.radroots/source/**` are
+ ignored, rebuildable repo-local staging/source cache; they are never
+ canonical source, tracked output, or independent release authority.
+
+## Working and verification rules
+
+- Inspect `git status --short`, relevant locks/contracts, package/project
+ manifests, source, tests, scripts, generated artifacts, and snapshots before
+ editing. Preserve unrelated work.
+- Run `cargo extbuild doctor` before the first mutating build, test, check,
+ dependency, package, generation, or snapshot command, then use the
+ repository's Make/script surfaces, which route work through
+ `cargo extbuild run -- ...`.
+- `make package-contract-check` is the narrow standalone source-lock,
+ package-lock, privacy, version, and forbidden-root guard.
+- `make bootstrap` performs networked source/artifact bootstrap. `make verify`
+ is the complete package, Xcode build/test, UI, and API-snapshot lane. Use an
+ explicitly installed simulator name when the default is unavailable.
+- Run the smallest credible target while iterating, followed by the complete
+ affected standalone lane. Never claim a command passed unless it ran
+ successfully; report missing Xcode, simulator, signing, or network
+ prerequisites exactly.
+- Prefer explicit typed state, deterministic transformations, bounded inputs,
+ narrow side effects, safe errors, and fail-closed validation. Avoid `unsafe`
+ and forced unwraps in production paths unless a local invariant is explicit
+ and tested.
+
+## Changes and external gates
+
+- Make one coherent, reviewable target-state change at a time. Keep source,
+ tests, machine contracts, generated outputs, locks, snapshots, and public
+ README material aligned.
+- Use focused commit subjects in the repository's established imperative
+ style.
+- Evidence that requires a normative product decision is recorded in the
+ parent-owned services-hardening authority, with the corresponding standalone
+ machine contract changed in the same ordered sequence. Do not create a local
+ human deviation ledger.
+- Do not push, tag, publish packages, deploy, change signing identities,
+ profiles, entitlements, registry ownership, or credentials without separate
+ explicit authority.
+
+## Definition of done
+
+- The requested behavior is complete at the correct Apple-host, generated FFI,
+ package, project, or application boundary.
+- Relevant package/Xcode/tool validation passed, generated output and locks are
+ fresh, public API snapshots agree, and zero `docs/**`, `.github/**`, or
+ `.act/**` roots exist.
+- The final review finds no secret exposure, hidden runtime ownership, private
+ dependency, unrelated change, or unreported skipped lane, and records whether
+ the next sequence step is safe.
diff --git a/docs/shared-engine-lifecycle-smoke-checklist.md b/docs/shared-engine-lifecycle-smoke-checklist.md
@@ -1,44 +0,0 @@
-# Shared engine lifecycle smoke checklist
-
-Run this checklist on an iOS 18 or newer simulator after regenerating the FFI
-artifact from `RadrootsFFI/source.lock`. Use a disposable app installation and
-do not enter a production identity.
-
-## Automated prerequisite
-
-- Run the `Radroots` scheme unit tests on an arm64 simulator.
-- Confirm the app and `SharedEngineLifecycleTests` both pass.
-- Confirm the generated binding has no post-stream start, next, or stop API.
-
-## Host custody and prompts
-
-- Create a local identity and accept the Apple user-presence prompt.
-- Background and foreground the app; confirm the identity remains locked until
- the Apple prompt succeeds and no secret appears in logs or diagnostics.
-- Cancel the prompt once; confirm the UI reports a bounded error and does not
- replace the selected Keychain item.
-- Sign out; confirm the runtime identity is cleared while the Keychain-backed
- identity remains available for a later unlock.
-- Reset local identity; confirm the Keychain item, public metadata, pending
- background work, and in-memory signer are all removed.
-
-## Relay, cancellation, and background behavior
-
-- Configure one valid relay and confirm read/write operations report
- `Available`; no connection count is displayed or exported.
-- Open and close the feed; confirm polling stops on disappearance and resumes
- with bounded fetches when reopened.
-- Send the app to the background during a fetch; confirm Apple background task
- scheduling remains host-owned and the app returns without a stuck spinner.
-- Terminate the app from the simulator switcher; confirm the next launch starts
- a fresh runtime and requires host restoration of the selected identity.
-
-## Logging and error presentation
-
-- Exercise invalid secret, invalid relay, and unavailable network paths.
-- Confirm SDK errors are presented through their secret-safe message and
- capability category, with no secret, raw event payload, or private path in
- unified logging, file logging, diagnostics JSON, or the UI.
-- Export diagnostics and confirm format
- `radroots_field_ios_diagnostics_v2` contains only configured relays,
- categorical source/sink availability, and the bounded last error.
diff --git a/scripts/verify-package-contract.sh b/scripts/verify-package-contract.sh
@@ -6,6 +6,14 @@ package="$repo_root/Package.swift"
source_lock="$repo_root/RadrootsFFI/source.lock"
consumer_lock="$repo_root/radroots.lib.source-lock.v1.toml"
+for forbidden_root in docs .github .act
+do
+ if [ -e "$repo_root/$forbidden_root" ] || [ -L "$repo_root/$forbidden_root" ]; then
+ echo "error: forbidden public repository root exists: $forbidden_root" >&2
+ exit 1
+ fi
+done
+
make_value() {
key=$1
awk -v key="$key" '$2 == key && $3 == ":=" { print $4 }' "$source_lock"