FI-WP-0005 T01-T03: owner declaration, publication decision, egress hosts.
- Owner declaration for the profiled fi-daily-research-brief (proposed): inputs, single-commit briefs/** grant, fast-forward-only publication, quality rules, model requirements without env selection, completion evidence and rollback pins. - Decision: origin publication is a typed grant on the run, not an executor default. - docs/sources-egress.yaml: 17 exact host:443 entries for the sandbox, tested for sand-boxer format and drift against the prose allowlist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 51320@bnt-lap001 Assistant-Session: 9d40b4c7-8e3c-42ee-b755-d658d4640d6c
This commit is contained in:
parent
7009521fdc
commit
5c5c298643
8 changed files with 396 additions and 4 deletions
113
activity-definitions/fi-daily-research-brief.declaration.yaml
Normal file
113
activity-definitions/fi-daily-research-brief.declaration.yaml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
# Owner declaration — fi-daily-research-brief (FI-WP-0005-T01)
|
||||
#
|
||||
# Answers rein-aharness d0b45acb / REINAH-WP-0003-T04: the owner-approved
|
||||
# replacement for the profile-absent `fi-research-brief` route. This file is
|
||||
# FI's authority over WHAT runs and under WHICH grant. It does not schedule
|
||||
# (activity-core), pick a rein/sandbox/model (glas-harness) or execute
|
||||
# (rein-aharness). Where another layer has not shipped the needed piece yet,
|
||||
# the field names the FI-WP-0005 task that tracks it.
|
||||
declaration_version: "1"
|
||||
definition_id: fi-daily-research-brief
|
||||
owner: freedom-intelligence
|
||||
approved_by: Bernd Worsch
|
||||
approved_at: "2026-09-22"
|
||||
status: proposed # -> active at FI-WP-0005-T08 cutover
|
||||
|
||||
execution:
|
||||
shape: agent # operator decision 2026-09-22 (option B)
|
||||
harness_profile_ref: harness.fi-research-brief@1.0.0 # requested, FI-WP-0005-T05; not yet in the Glas catalog
|
||||
selection: harness_profile_ref only. No label or approach_hint routing, no
|
||||
fallback to the compatibility executor once cut over.
|
||||
|
||||
inputs:
|
||||
# Read from the checked-out workspace at the run's base commit.
|
||||
brief_date:
|
||||
type: date
|
||||
tz: Europe/Berlin
|
||||
source: activity-core due item (context.item.date)
|
||||
repository_files:
|
||||
- docs/sources-allowlist.md
|
||||
- docs/daily-brief-playbook.md
|
||||
- briefs/_template.md
|
||||
- inventory/RESERVE-STATUS.md
|
||||
- research/2026-07-24-baseline-field-survey.md
|
||||
- research/2026-07-24-nas-strategic-collection-plan.md
|
||||
repository_globs:
|
||||
- inventory/catalog/*.yaml # authority for sizes, licenses, collection status
|
||||
prior_briefs:
|
||||
names: last 5 by date, excluding brief_date
|
||||
full_text: most recent 1
|
||||
git_log: last 12 commits, oneline
|
||||
network:
|
||||
egress_hosts: docs/sources-egress.yaml # FI-WP-0005-T03; model route is profile-owned
|
||||
secrets: none. The run reads no FI credential. Model credentials stay with
|
||||
the profile's owner route (Glas / sand-boxer).
|
||||
|
||||
outputs:
|
||||
artifact: briefs/{yyyy}/{mm}/{date}.md
|
||||
format: briefs/_template.md, axes A–D, collection-candidate section
|
||||
exactly_one_new_file: true
|
||||
must_not_modify_existing_files: true
|
||||
|
||||
repository_grant:
|
||||
# Grant v1 fields (activity-core RepositoryGrant). v1 rejects publish=true,
|
||||
# so publication rides on grant v2 (FI-WP-0005-T04).
|
||||
version: "2" # requested; v1 shape below validated against activity-core b63131e+
|
||||
allowed_paths:
|
||||
- briefs/**
|
||||
commit_count: {min: 1, max: 1}
|
||||
publication:
|
||||
remote: origin
|
||||
ref: main
|
||||
mode: fast-forward-only
|
||||
decision: docs/decisions/2026-09-22-brief-origin-publication.md
|
||||
commit_message: "FI daily research brief {date}"
|
||||
|
||||
quality_rules:
|
||||
# Acceptance for canary comparison (FI-WP-0005-T07) and prompt contract.
|
||||
- inventory/catalog is the authority. Do not re-announce cataloged models
|
||||
as new, and never state sizes or licenses that contradict the catalog.
|
||||
- Every parameter count, size, price or benchmark claim cites a primary
|
||||
source that was fetched in this run. If it is not verifiable, say so
|
||||
instead of estimating.
|
||||
- Deltas only, measured against prior briefs and the baseline, not a resurvey.
|
||||
- Cover axes A–D, or state explicitly that an axis had no delta.
|
||||
- Rumor (social media, unsourced aggregators) is not reported as confirmed.
|
||||
- No credentials, customer data or model weights in the brief.
|
||||
|
||||
model:
|
||||
# FI states requirements; the Glas profile pins provider/model/route.
|
||||
model_class: frontier
|
||||
required_capabilities: [tool_use, web_fetch_via_https_proxy, long_context]
|
||||
limits_hint: {timeout_seconds: 1800, max_turns: 60}
|
||||
constraints:
|
||||
- No Binky-named variables (BRIEF_DAILY_MODEL, MAIL_TRIAGE_MODEL) and no
|
||||
process-environment model selection. The profile version is the only selector.
|
||||
- The playbook rule "no Claude Code / Codex on railiance01" means no
|
||||
host-installed agent. A pinned agent executable inside the Glas sandbox is
|
||||
acceptable only if the profile owner confirms it is not a host
|
||||
installation. Operator to confirm (FI-WP-0005-T05).
|
||||
|
||||
completion:
|
||||
event: fi_daily_brief
|
||||
required_detail:
|
||||
date: brief_date
|
||||
path: outputs.artifact
|
||||
pushed: true
|
||||
origin_sha: 40-hex commit on origin/main that contains the artifact
|
||||
harness_profile_ref: execution.harness_profile_ref
|
||||
due_resolution: published-artifact resolver (FI-WP-0005-T04). The day
|
||||
clears only if the artifact is on origin/main AND the event says
|
||||
pushed=true. In the interim, fi_brief_status (activity-core 289aff3), same semantics.
|
||||
on_failure: executor_run ok=false, no fi_daily_brief, day stays due.
|
||||
independent_audit: scripts/verify_brief_durability.py --require-date {date}
|
||||
|
||||
rollback:
|
||||
pins:
|
||||
- glas profile version (previous harness.fi-research-brief@x.y.z)
|
||||
- this declaration and the definition, by git revision in this repo
|
||||
procedure: pin the previous profile version or revert the definition
|
||||
revision, then sync activity-core definitions. Until the legacy expiry
|
||||
(2026-12-31) the compatibility executor rein-aharness@11020e8 remains a
|
||||
manual one-shot recovery. There is no host timer (FI-WP-0005-T06).
|
||||
evidence_required: one exercised rollback at cutover (FI-WP-0005-T08)
|
||||
|
|
@ -65,5 +65,9 @@ action:
|
|||
5. [x] Executor: `rein-aharness fi-research-brief` + `scripts/railiance-rhythm/`
|
||||
(install on railiance01; not workstation cron)
|
||||
|
||||
Migration (FI-WP-0005): the owner declaration for the profiled replacement is
|
||||
`fi-daily-research-brief.declaration.yaml` (status `proposed`). This definition
|
||||
stays on the compatibility route until the T08 cutover.
|
||||
|
||||
Layers: activity-core (when/what/where) → rein-aharness (execute) → this repo.
|
||||
See `docs/recurrence-ops.md` and `activity-core/docs/recurring-automations-playbook.md`.
|
||||
|
|
|
|||
60
docs/decisions/2026-09-22-brief-origin-publication.md
Normal file
60
docs/decisions/2026-09-22-brief-origin-publication.md
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# Decision: Origin publication of daily briefs is an explicit, typed grant
|
||||
|
||||
**Date:** 2026-09-22
|
||||
**Status:** accepted
|
||||
**Decided by:** Bernd Worsch (operator), FI owner
|
||||
**Affects:** `activity-definitions/fi-daily-research-brief.md`,
|
||||
`activity-definitions/fi-daily-research-brief.declaration.yaml`, FI-WP-0005
|
||||
**Supersedes:** the grant wording in FI-WP-0004-T04, which granted "origin
|
||||
publication as a named capability of `fi-research-brief`". That capability
|
||||
lived inside one rein command. This decision moves it to the queued run's
|
||||
repository grant.
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
A brief day counts only when the brief is on `origin/main` (FI-WP-0004). The
|
||||
executor therefore has to push. rein-aharness (`d0b45acb`, REINAH-WP-0003-T04)
|
||||
requires that publication be a separate, owner-approved decision, not a
|
||||
default of the executor. activity-core repository-grant v1 is local-only and
|
||||
rejects `publish: true`.
|
||||
|
||||
## Decision
|
||||
|
||||
1. **FI grants publication, scoped exactly:**
|
||||
- remote `origin`, ref `main`
|
||||
- mode **fast-forward only**: no force push, no other refs, no tags
|
||||
- only commits whose changes stay within `briefs/**`
|
||||
- at most one commit per run
|
||||
2. **The grant rides on the run, not the executor.** It is carried as
|
||||
activity-core repository-grant v2 `publication` (requested in FI-WP-0005-T04).
|
||||
No rein, profile or tool may publish FI content without that grant on the
|
||||
claimed `ops_run`.
|
||||
3. **Failure semantics:**
|
||||
- Push rejected or failed: the run fails, no `fi_daily_brief` is posted,
|
||||
and the day stays due.
|
||||
- Non-fast-forward (origin moved): the executor may rebase its single
|
||||
brief commit onto the new origin head once, then retry. A second failure
|
||||
is a failed run. It never merges and never forces.
|
||||
- Success requires `origin_sha` evidence, and activity-core close
|
||||
reconciliation checks it against the grant.
|
||||
4. **Until grant v2 is live**, the compatibility path (`rein-aharness
|
||||
fi-research-brief`, commit `11020e8`) continues under FI-WP-0004-T04 semantics.
|
||||
It ends at cutover (FI-WP-0005-T08) or at the legacy expiry, whichever
|
||||
comes first.
|
||||
|
||||
## Not granted
|
||||
|
||||
- Writes outside `briefs/**`. The catalog, inventory, workplans and docs stay
|
||||
human- or workplan-driven.
|
||||
- Publication to any other remote or mirror.
|
||||
- Opening PRs or issues, or posting to other external systems.
|
||||
|
||||
## Consequences
|
||||
|
||||
- activity-core needs grant v2 and origin-SHA close evidence (FI-WP-0005-T04).
|
||||
- The Glas tool profile must be able to push, but only under a grant
|
||||
(FI-WP-0005-T05).
|
||||
- `scripts/verify_brief_durability.py` remains the independent audit of the
|
||||
result.
|
||||
|
|
@ -3,6 +3,11 @@
|
|||
Standing channels for Freedom Intelligence briefs (axes A–D). Prefer **primary**
|
||||
sources over aggregators. This is a watchlist, not a scrape mandate.
|
||||
|
||||
Automated runs reach the network only through the hosts in
|
||||
[`sources-egress.yaml`](sources-egress.yaml) (FI-WP-0005-T03). Adding a
|
||||
channel here that needs a new host means adding that host there too;
|
||||
`scripts/test_sources_egress.py` checks the two stay in step.
|
||||
|
||||
---
|
||||
|
||||
## Axis A — Frontier & commercial
|
||||
|
|
|
|||
99
docs/sources-egress.yaml
Normal file
99
docs/sources-egress.yaml
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
# Network egress for the daily research brief sandbox (FI-WP-0005-T03).
|
||||
#
|
||||
# Machine-readable companion to docs/sources-allowlist.md. The Glas profile
|
||||
# for fi-daily-research-brief declares exactly these hosts in
|
||||
# network.egress (default: deny). The model provider route is NOT listed
|
||||
# here; it belongs to the profile (glas-harness), not to FI.
|
||||
#
|
||||
# sand-boxer rules (docs/bwrap-egress.md): exact lowercase DNS names, port 443
|
||||
# only, no wildcards, no IP literals. Enforcement is by destination, not by
|
||||
# path: every host below is a whole-host trust decision. Keep the list minimal.
|
||||
#
|
||||
# `channel` must appear verbatim in docs/sources-allowlist.md
|
||||
# (scripts/test_sources_egress.py enforces this so the two cannot drift).
|
||||
version: 1
|
||||
hosts:
|
||||
# Axis A — frontier & commercial
|
||||
- host: openai.com:443
|
||||
axes: [A]
|
||||
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||
why: Release notes, model pages, API pricing. Returned 403 to a plain
|
||||
client on 2026-09-22 (bot protection); may be unreadable unattended.
|
||||
- host: www.anthropic.com:443
|
||||
axes: [A]
|
||||
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||
why: News and model announcements (apex redirects here).
|
||||
- host: platform.claude.com:443
|
||||
axes: [A]
|
||||
channel: Model cards for API models
|
||||
why: Model overview, context limits, pricing tables (docs.anthropic.com
|
||||
now 301-redirects here, 2026-09-22).
|
||||
- host: blog.google:443
|
||||
axes: [A]
|
||||
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||
why: Gemini release announcements.
|
||||
- host: ai.google.dev:443
|
||||
axes: [A]
|
||||
channel: Official pricing pages
|
||||
why: Gemini API models and pricing.
|
||||
- host: x.ai:443
|
||||
axes: [A]
|
||||
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||
why: Grok release notes. Returned 403 to a plain client on 2026-09-22.
|
||||
- host: api-docs.deepseek.com:443
|
||||
axes: [A, B]
|
||||
channel: OpenAI / Anthropic / Google / xAI / DeepSeek blogs & release notes
|
||||
why: DeepSeek news, API pricing and model list.
|
||||
- host: arena.ai:443
|
||||
axes: [A]
|
||||
channel: LMSYS / Arena / artificialanalysis-class charts
|
||||
why: Directional leaderboard only; note gaming risk (lmarena.ai
|
||||
301-redirects here, 2026-09-22).
|
||||
- host: artificialanalysis.ai:443
|
||||
axes: [A]
|
||||
channel: LMSYS / Arena / artificialanalysis-class charts
|
||||
why: Price/performance charts, directional.
|
||||
- host: www.swebench.com:443
|
||||
axes: [A, D]
|
||||
channel: SWE-bench Verified / Live leaderboards
|
||||
why: Harness+model pairs.
|
||||
# Axis B — edge / local / open
|
||||
- host: huggingface.co:443
|
||||
axes: [B, C]
|
||||
channel: Hugging Face org feeds
|
||||
why: Model cards, licenses, sizes via /api/models. No weight download
|
||||
(weight CDN hosts are deliberately absent).
|
||||
- host: ollama.com:443
|
||||
axes: [B]
|
||||
channel: llama.cpp, vLLM, MLX, Ollama release notes
|
||||
why: Ollama library and release notes.
|
||||
# Axes B/C/D — GitHub-hosted releases (llama.cpp, vLLM, MLX, Unsloth, TRL,
|
||||
# OpenHands, Aider, SWE-agent, OpenCode, Cline, ...)
|
||||
- host: github.com:443
|
||||
axes: [B, C, D]
|
||||
channel: OpenHands, Aider, SWE-agent, OpenCode, Cline repos/releases
|
||||
why: Release pages for runtimes, training tools and harnesses.
|
||||
- host: api.github.com:443
|
||||
axes: [B, C, D]
|
||||
channel: llama.cpp, vLLM, MLX, Ollama release notes
|
||||
why: Structured release listing instead of scraping HTML.
|
||||
# Axis C — training & specialization
|
||||
- host: arxiv.org:443
|
||||
axes: [C]
|
||||
channel: arXiv cs.LG, cs.CL, cs.AI (recent)
|
||||
why: Abstracts and listings.
|
||||
- host: export.arxiv.org:443
|
||||
axes: [C]
|
||||
channel: arXiv cs.LG, cs.CL, cs.AI (recent)
|
||||
why: arXiv query API (the sanctioned programmatic endpoint).
|
||||
# Axis D — harness & fleet
|
||||
- host: modelcontextprotocol.io:443
|
||||
axes: [D]
|
||||
channel: MCP / tool-protocol standards
|
||||
why: MCP specification and changelog.
|
||||
# Deliberately absent:
|
||||
# - Model provider API hosts (profile-owned route).
|
||||
# - Hugging Face / GitHub content CDNs (no weight or asset download in briefs).
|
||||
# - Social media / X (allowlist: rumor is not confirmation).
|
||||
# - Internal Coulomb repos (sand-boxer, activity-core): read from the
|
||||
# checked-out workspace or hub, not over the network.
|
||||
42
scripts/test_declaration.py
Normal file
42
scripts/test_declaration.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""The fi-daily-research-brief owner declaration parses and its references resolve."""
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
DECLARATION = ROOT / 'activity-definitions' / 'fi-daily-research-brief.declaration.yaml'
|
||||
|
||||
|
||||
class DeclarationTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.doc = yaml.safe_load(DECLARATION.read_text(encoding='utf-8'))
|
||||
|
||||
def test_referenced_files_exist(self):
|
||||
inputs = self.doc['inputs']
|
||||
paths = list(inputs['repository_files'])
|
||||
paths.append(inputs['network']['egress_hosts'])
|
||||
paths.append(self.doc['repository_grant']['publication']['decision'])
|
||||
for rel in paths:
|
||||
self.assertTrue((ROOT / rel).is_file(), rel)
|
||||
|
||||
def test_grant_is_single_commit_within_briefs(self):
|
||||
grant = self.doc['repository_grant']
|
||||
self.assertEqual(grant['allowed_paths'], ['briefs/**'])
|
||||
self.assertEqual(grant['commit_count'], {'min': 1, 'max': 1})
|
||||
self.assertEqual(grant['publication'],
|
||||
{'remote': 'origin', 'ref': 'main', 'mode': 'fast-forward-only',
|
||||
'decision': grant['publication']['decision']})
|
||||
|
||||
def test_completion_requires_published_evidence(self):
|
||||
detail = self.doc['completion']['required_detail']
|
||||
self.assertIs(detail['pushed'], True)
|
||||
self.assertIn('origin_sha', detail)
|
||||
|
||||
def test_no_environment_model_selection(self):
|
||||
self.assertNotIn('env', self.doc['model'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
51
scripts/test_sources_egress.py
Normal file
51
scripts/test_sources_egress.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
"""docs/sources-egress.yaml stays valid for sand-boxer and in step with the prose allowlist."""
|
||||
from pathlib import Path
|
||||
import re
|
||||
import unittest
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
EGRESS = ROOT / 'docs' / 'sources-egress.yaml'
|
||||
ALLOWLIST = ROOT / 'docs' / 'sources-allowlist.md'
|
||||
# sand-boxer bwrap-egress: exact lowercase DNS name, port 443, no wildcard or IP literal.
|
||||
HOST = re.compile(r'^(?=.{1,253}:443$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}:443$')
|
||||
MAX_HOSTS = 24 # every host is a whole-host trust decision; raise only deliberately
|
||||
|
||||
|
||||
class SourcesEgressTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.doc = yaml.safe_load(EGRESS.read_text(encoding='utf-8'))
|
||||
cls.hosts = cls.doc['hosts']
|
||||
cls.prose = ALLOWLIST.read_text(encoding='utf-8')
|
||||
|
||||
def test_version(self):
|
||||
self.assertEqual(self.doc['version'], 1)
|
||||
|
||||
def test_host_format(self):
|
||||
for entry in self.hosts:
|
||||
self.assertRegex(entry['host'], HOST)
|
||||
|
||||
def test_no_duplicates_and_bounded(self):
|
||||
names = [e['host'] for e in self.hosts]
|
||||
self.assertEqual(len(names), len(set(names)))
|
||||
self.assertLessEqual(len(names), MAX_HOSTS)
|
||||
|
||||
def test_entries_complete(self):
|
||||
for entry in self.hosts:
|
||||
self.assertEqual(set(entry), {'host', 'axes', 'channel', 'why'}, entry['host'])
|
||||
self.assertTrue(entry['why'].strip(), entry['host'])
|
||||
self.assertTrue(set(entry['axes']) <= set('ABCD'), entry['host'])
|
||||
|
||||
def test_every_axis_covered(self):
|
||||
covered = {axis for e in self.hosts for axis in e['axes']}
|
||||
self.assertEqual(covered, set('ABCD'))
|
||||
|
||||
def test_channel_named_in_prose_allowlist(self):
|
||||
for entry in self.hosts:
|
||||
self.assertIn(entry['channel'], self.prose, entry['host'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
@ -70,7 +70,7 @@ network egress beyond a model provider.
|
|||
|
||||
```task
|
||||
id: FI-WP-0005-T01
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "bf8c1870-bdca-51d6-beaf-c5f000037205"
|
||||
```
|
||||
|
|
@ -86,27 +86,39 @@ publication policy (reference T02), and rollback. No Binky-named env vars.
|
|||
**Done when:** the declaration is committed, and every field rein listed in
|
||||
`d0b45acb` maps to a concrete value or to a named follow-up task here.
|
||||
|
||||
**2026-09-22:** Done. `activity-definitions/fi-daily-research-brief.declaration.yaml`
|
||||
(status `proposed`). It covers profile ref (pending T05), inputs, outputs, grant
|
||||
(its v1 fields validate against activity-core `RepositoryGrant`; publication pending
|
||||
T04), quality rules, model requirements without env selection, completion
|
||||
evidence and rollback pins. `scripts/test_declaration.py` checks it. Open
|
||||
operator question: whether a pinned agent executable inside the Glas sandbox
|
||||
satisfies the playbook's "no Claude Code / Codex on railiance01" rule.
|
||||
|
||||
### T02 — Publication decision record
|
||||
|
||||
```task
|
||||
id: FI-WP-0005-T02
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "25475ede-ebd9-5c31-8c22-718e30acf8ac"
|
||||
```
|
||||
|
||||
`docs/decisions/2026-09-XX-brief-origin-publication.md`: FI grants
|
||||
`docs/decisions/2026-09-22-brief-origin-publication.md`: FI grants
|
||||
fast-forward-only publication of `briefs/**` to `origin/main`; no force, no
|
||||
other refs; publication failure fails the run and leaves the day due. Supersedes
|
||||
the implicit grant wording in FI-WP-0004-T04.
|
||||
|
||||
**Done when:** the decision is committed and cited by T01 and T04.
|
||||
|
||||
**2026-09-22:** Done. Adds a single rebase-and-retry on non-fast-forward;
|
||||
it never merges or forces. Cited by the declaration and the activity-core
|
||||
proposal `8ee9a6ab`.
|
||||
|
||||
### T03 — Machine-readable source host list
|
||||
|
||||
```task
|
||||
id: FI-WP-0005-T03
|
||||
status: todo
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "9b92d7f4-f4c8-5ce5-9367-462653515e90"
|
||||
```
|
||||
|
|
@ -120,6 +132,12 @@ path, so every host is a trust decision.
|
|||
**Done when:** the list is committed with a test, and the host count and the
|
||||
rationale for each host are recorded.
|
||||
|
||||
**2026-09-22:** Done. `docs/sources-egress.yaml` has 17 hosts covering axes A–D.
|
||||
`scripts/test_sources_egress.py` checks sand-boxer format, the 24-host cap and
|
||||
that each channel is named in the prose allowlist. A live check replaced
|
||||
redirecting hosts (docs.anthropic.com → platform.claude.com, lmarena.ai →
|
||||
arena.ai). openai.com and x.ai return 403 to plain clients, which is noted.
|
||||
|
||||
### T04 — activity-core handoff: grant v2 publication + generic due resolver
|
||||
|
||||
```task
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue