unify: merge the GitHub line into Gitea, settled against real service contracts #6

Merged
admin merged 9 commits from unify/github-main-2026-07-28 into main 2026-08-09 09:31:05 +00:00
Owner

+8 Gitea, +6 GitHub — both sides had work the other lacked. Merged so both survive.

An independent reviewer was pointed at this branch with one instruction: find what was
dropped. Verdict: 0 dropped behaviours, 17 confirmed survived.

The conflicts were settled against real contracts, not by preference

The four src/clients/*.ts files were the crux — both sides rewrote them independently.
Rather than pick a side, the resolver read the target services' actual contracts:

  • st0re-client.ts — Gitea POSTed to /v1/st0re/artifacts. Reading sax3l/st0re
    src/api/routes/artifacts.ts shows that path is registered GET-only; the register
    endpoint is /v1/st0re/artifacts/register, which is GitHub's. Gitea's client would
    never have registered anything.
    GitHub's endpoint wins on evidence. Gitea's URL
    normalisation, response-body-in-error and required retention_policy/data_residency
    all kept.
  • n0d-client.ts — the two sides disagreed on state vs status and on the enum.
    sax3l/n0d packages/schemas/n0d.job.schema.json requires status with a 13-state
    enum and carries the note "Do not add 'succeeded' — that is 'completed' under a
    different name."
    GitHub's field name was right, Gitea's vocabulary was wrong. Both
    historical type names kept as aliases so no import breaks.
  • cl0ud-client.ts — kept Gitea's fail-closed normalisation
    (body.decision ?? "deny"). GitHub returned res.json() raw, so a 200 with a missing
    decision field would have read as permitted. This is the security-relevant half.

What the reviewer confirmed survived

GitHub's 17 audit bug-fixes (byte-identical), the CI quality gate, the .gitignore
blanket-.env fix and its !.env.example negation, the added platform clients and
registry services — plus Gitea's Iceberg write-boundary work, its Zod parseBody
gates on all four lakehouse routes, its Zitadel/AUTH_ENFORCE env block, and its
X-Tenant-Id/X-Actor-Id threading.

Measured

Gitea main GitHub main Merged
pnpm install ok FAILS (packages field missing) ok — Gitea's workspace fix carries over
pnpm test 121 passed / 1 skip 88 passed 121 passed / 1 skip
typecheck (scoped) exit 0 — exit 0
whole-repo tsc 9 errors 0 the same 9, line numbers shifted only

GitHub's 88 tests are a strict subset of Gitea's file set, so no GitHub-only test was
lost. The 1 skip is honest: iceberg-write-service.realinfra.test.ts skips because
ST0RE returned 401, and says so rather than fabricating a pass.

Two things left unsettled ON PURPOSE

packages/schemas/0pt.{lineage_event,signal}.schema.json — the two lines disagree on
field vocabulary (producer object vs flat string; entity_id/observed_at/
confidence_level vs entity_key/detected_at/numeric confidence). Nothing in the
repo reads, writes or validates against either file
, so the code cannot decide it. Both
vocabularies are retained as optional properties with the disagreement recorded in each
schema's own description. Whoever builds signal detection picks one pair and deletes
the other.

Also: typecheck is scoped to src/+tests/ as blocking and whole-repo as advisory.
The 9 whole-repo errors are all Wave-2 Zod schemas typing a field as string where the
service wants a narrower union — tightening them changes which request bodies the routes
accept, which is a behaviour change that does not belong in a merge.

One review finding, fixed

The tree asserted the banned scraper stack was "excluded by design" while all 64 files of
services/scrapers/ are present. The README now states the policy and the state, and
points at PR #1, which exists to delete them.
Deleting them here would fold a policy change into a history merge.

Backup: backup/pre-github-unify-2026-07-28.

**+8 Gitea, +6 GitHub — both sides had work the other lacked.** Merged so both survive. An independent reviewer was pointed at this branch with one instruction: find what was dropped. Verdict: **0 dropped behaviours, 17 confirmed survived.** ### The conflicts were settled against real contracts, not by preference The four `src/clients/*.ts` files were the crux — both sides rewrote them independently. Rather than pick a side, the resolver read the target services' actual contracts: - **`st0re-client.ts`** — Gitea POSTed to `/v1/st0re/artifacts`. Reading `sax3l/st0re` `src/api/routes/artifacts.ts` shows that path is registered **GET-only**; the register endpoint is `/v1/st0re/artifacts/register`, which is GitHub's. **Gitea's client would never have registered anything.** GitHub's endpoint wins on evidence. Gitea's URL normalisation, response-body-in-error and required `retention_policy`/`data_residency` all kept. - **`n0d-client.ts`** — the two sides disagreed on `state` vs `status` and on the enum. `sax3l/n0d` `packages/schemas/n0d.job.schema.json` requires `status` with a 13-state enum and carries the note *"Do not add 'succeeded' — that is 'completed' under a different name."* GitHub's field name was right, Gitea's vocabulary was wrong. Both historical type names kept as aliases so no import breaks. - **`cl0ud-client.ts`** — kept **Gitea's fail-closed normalisation** (`body.decision ?? "deny"`). GitHub returned `res.json()` raw, so a 200 with a missing `decision` field would have read as permitted. This is the security-relevant half. ### What the reviewer confirmed survived GitHub's 17 audit bug-fixes (byte-identical), the CI quality gate, the `.gitignore` blanket-`.env` fix **and** its `!.env.example` negation, the added platform clients and registry services — **plus** Gitea's Iceberg write-boundary work, its Zod `parseBody` gates on all four lakehouse routes, its Zitadel/`AUTH_ENFORCE` env block, and its `X-Tenant-Id`/`X-Actor-Id` threading. ### Measured | | Gitea main | GitHub main | Merged | |---|---|---|---| | `pnpm install` | ok | **FAILS** (`packages field missing`) | ok — Gitea's workspace fix carries over | | `pnpm test` | 121 passed / 1 skip | 88 passed | **121 passed / 1 skip** | | `typecheck` (scoped) | exit 0 | — | **exit 0** | | whole-repo tsc | 9 errors | 0 | **the same 9**, line numbers shifted only | GitHub's 88 tests are a strict subset of Gitea's file set, so no GitHub-only test was lost. The 1 skip is honest: `iceberg-write-service.realinfra.test.ts` skips because ST0RE returned 401, and says so rather than fabricating a pass. ### Two things left unsettled ON PURPOSE `packages/schemas/0pt.{lineage_event,signal}.schema.json` — the two lines disagree on field vocabulary (`producer` object vs flat string; `entity_id`/`observed_at`/ `confidence_level` vs `entity_key`/`detected_at`/numeric `confidence`). **Nothing in the repo reads, writes or validates against either file**, so the code cannot decide it. Both vocabularies are retained as optional properties with the disagreement recorded in each schema's own `description`. Whoever builds signal detection picks one pair and deletes the other. Also: `typecheck` is scoped to `src/`+`tests/` as blocking and whole-repo as advisory. The 9 whole-repo errors are all Wave-2 Zod schemas typing a field as `string` where the service wants a narrower union — tightening them changes which request bodies the routes accept, which is a behaviour change that does not belong in a merge. ### One review finding, fixed The tree asserted the banned scraper stack was "excluded by design" while all 64 files of `services/scrapers/` are present. The README now states the policy **and** the state, and points at [PR #1](https://git.siax.io/sax3l/0pt/pulls/1), which exists to delete them. Deleting them here would fold a policy change into a history merge. **Backup:** `backup/pre-github-unify-2026-07-28`.
admin added 8 commits 2026-07-28 10:56:57 +00:00
The 0pt data-engine build has been broken on main since 2026-07-08 (commit
c897311). document-capture-service.ts, document-extraction-service.ts,
source-query-service.ts, external-writeback-service.ts (and, more recently,
dataset-iceberg-mapping-service.ts, iceberg-write-service.ts,
source-rate-policy-service.ts) all import six platform client modules and two
registry services that were never committed: src/clients/{aud0,cl0ud,n0d,
st0re}-client.ts, src/services/{dataset,source}-service.ts, plus
src/types/{dataset,source}.ts. `next build` failed with 17 "Module not found"
errors, and every route under app/api/0pt/* returned HTTP 500 in dev with the
Turbopack compile error leaked straight into the JSON response body.

This adds the missing files, following the same fetch-based client shape
already established by src/clients/st0re-lakehouse-client.ts (thin interface,
HTTP implementation, deterministic in-memory mock used when no base URL is
configured) and the same "pure core, thin in-memory registry, AUD0-evented
mutation" shape the existing SourceRatePolicyService/DatasetIcebergMappingService
already use for DatasetService/SourceService. Each new client mock is
documented as a mock/degrade path, never a fabricated success, per this
repo's CLAUDE.md honesty doctrine.

Also wires up "typecheck" and "test" npm scripts (tsc --noEmit / vitest run)
and adds vitest as a devDependency -- previously `pnpm test` failed
immediately with ERR_PNPM_NO_SCRIPT even though 13 test files (~89 cases)
already existed under tests/p0/.

Verified: `pnpm run typecheck` clean, `pnpm run test` 88 passed / 1 todo
(pre-existing live-ST0RE-only skip), `pnpm run build` exits 0 (39/39 routes
compiled, only the pre-existing intentional optional `mssql` import warning
remains). Re-verified live on port 4097: GET /api/0pt/sources/rate-policies,
GET /api/0pt/lakehouse/mappings, POST /api/0pt/documents/capture, GET
/api/0pt/documents/[id]/extraction, and both GET/POST
/api/0pt/sources/[id]/query now return real application responses (200/400/405)
instead of HTTP 500 with a leaked compile error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fix: restore 0pt build — add missing platform clients + registry services
.env.example was referenced by README.md and required by docs/09-build-plan.md
(Phase 0) but never existed in the repo. Root cause: .gitignore's `.env*` rule
silently ignored it too, so `git add .env.example` was always a no-op even if
someone created it locally.

- Add .gitignore exception: `!.env.example`.
- Add .env.example covering every process.env.* read found in this pass
  (grep-verified across app/, lib/, src/), organized by concern, each section
  marked "wired in code today" or "documented target, not yet read by code"
  per docs/08-infrastructure.md. No real values; matches repo convention.

Excluded ODOO_BASE_URL: only appears inside a comment describing a past
refactor away from module-level env reads, not an actual process.env read.

pnpm test: 88 passed, 1 todo, 0 failures (13 files, tests/**/*.test.ts).
tsc --noEmit: clean.
* docs: full accuracy overhaul, grounded claim-by-claim in real code

Every doc in this repo (CLAUDE.md, README.md, SECURITY.md, docs/*.md) was
audited and rewritten by a multi-pass process: independent rewrite per
cluster, adversarial re-verification of that rewrite against the actual
code, then a final cross-doc consistency pass — each stage re-checking
claims against the repo directly rather than trusting the previous stage.

Two corrections matter most:

1. docs/ICEBERG_WRITE_BOUNDARY.md, docs/11-lakehouse-write-plan.md, and
   docs/P0_QUERY_SOURCE_FLOW.md asserted src/services/quality-check-service.ts,
   quality-report-service.ts, src/data-platform/services/catalog-service.ts,
   and sql/002_p0_dataset_quality.sql/sql/003_*.sql as real, tested code.
   git log --all across every branch shows zero commits for any of these
   paths, ever. 0pt's data-quality/QA enforcement does not exist in code.
   Corrected everywhere, with a new docs/P0_DATASET_QUALITY_FLOW.md added
   as an explicit target-spec (not-yet-built) replacement.

2. github.com/sax3l/0pt (this repo) and git.siax.io/sax3l/0pt (Gitea) are
   two diverged remotes sharing part of the same history (services/api/
   workers/adaptive_router.py is byte-identical between them). Gitea's main
   independently accumulated a WAF-bypass/proxy-rotation scraper stack in
   three 2026-07-13 commits, since removed via a Gitea PR; GitHub's main
   never had it. Which remote is canonical/deployed is unresolved — flagged
   consistently across the corpus, not decided here.

Also newly and consistently documented: the tenant_id/project_id-read-from-
client-body gap on the P0 lakehouse/rate-policy/source-query routes (no
auth/session system exists anywhere in this repo yet); that every CL0UD/
N0D/AUD0/ST0RE platform client is real but mock-only (zero process.env
reads for any of their *_URL vars); that two P0 mutation routes
(lakehouse/mappings, sources/rate-policies) always fail over HTTP today
because their prerequisite entity can never be created via any route; a
schema bug in sql/004 (FK references to opt_datasets/opt_sources, which
don't exist); and that 0pt.app's live deployment was independently
confirmed (curled this pass) to be running this exact codebase with
DATABASE_URL/REDIS_URL unset in production.

New file: docs/12-edge-capability-api.md — the edge-native P0 TypeScript
capability contract (app/api/0pt/*, /api/screen, /api/ai/parse), previously
undocumented and distinct from docs/04-api.md's FastAPI-engine-only scope.

Verified before commit: tsc --noEmit clean; vitest run 88 passed, 1 todo,
0 failures (13 files) — docs-only change, no source touched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* docs: reflect PR #5's lakehouse-mapping-registry + status-code fixes

Follow-up to keep docs/12-edge-capability-api.md accurate once both PRs
land: fix/0pt-full-bug-hunt (#5) fixed the shared-instance bug in the
lakehouse mapping routes and added proper status-code mapping to the
document extraction route. This doc was written against the pre-fix
state in the same pass that added it, so it needs the same correction.

Does not claim the lakehouse write path fully works now -- the deeper
dataset-registration gap (no route ever calls DatasetService.registerDataset)
is unchanged and still blocks it end-to-end; only the shared-instance half
of the bug is fixed.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* docs: correct stale quality-check-service.ts comment references

Two source comments still cited src/services/quality-check-service.ts as an
existing precedent. It doesn't exist anywhere in this repo's history (git
log --all: zero commits, any branch, ever) -- confirmed during the earlier
full-doc-corpus accuracy pass. Points each comment at the real precedent
instead (document-extraction-service.ts / iceberg-write-service.ts).

Applied from task_05ec36aa, spun off during that pass.

* fix: 17 confirmed bugs from full-repo audit (edge + Python engine)

Found by an 8-finder bug hunt across app/api, src/services, src/clients,
frontend, the Python engine, the data layer, config/infra, and tests, then
independently adversarially verified per finding (32 raw findings -> 27
confirmed real bugs; 5 refuted). This commit applies the 17 confirmed as
safe, mechanical fixes -- no architecture/design decision required. The
other 10 need a decision and are reported separately, not touched here.

Most consequential, app/api/payments/[order_id]/deposit/route.ts:
the client-supplied Origin request header was trusted unsanitized both as
a server-side fetch target (SSRF) and as Stripe Checkout success/cancel
redirect URLs (open redirect tied to a real payment flow), and a failed
order lookup silently fell through to a hardcoded deposit amount instead
of 404. Fixed by reading the order directly via lib/orders-store.ts
(mirroring the sibling release/route.ts, which already did this correctly)
instead of both trusting the Origin header and self-issuing an HTTP fetch.

Also fixed:
- 5 routes (orders, orders/[id], estimates, subscriptions, ai/parse) that
  500'd instead of 400ing on a literal JSON `null` body, since req.json()
  resolves (not rejects) for that input and bypasses the try/catch guard.
- app/api/0pt/lakehouse/mappings/{,[mappingId]/{,writes/}}route.ts each
  instantiated their own private service instances, so a mapping created
  via POST was invisible to the sibling GET and writes routes even before
  the separately-tracked dataset-registration gap. Extracted a shared
  singleton module, src/services/lakehouse-mapping-registry.ts.
- app/api/0pt/documents/[documentId]/extraction/route.ts collapsed every
  error (not-configured, policy-denied, policy-approval-required,
  not-found) into a blanket 400; now status-mapped like the sibling
  sources/[sourceId]/query route.
- app/api/vehicles/route.ts: plate query param wasn't URL-encoded before
  being concatenated into the outbound RDW request, allowing extra query
  parameters to be injected; added a strict allowlist + encodeURIComponent.
- app/api/uploads/route.ts: POST returned a fake 200 success with
  put_url: null even when "configured", instead of continuing to report
  501 until presign generation is actually implemented.
- src/adapters/document-intelligence-adapter.ts: the result-polling loop
  never checked response.ok, so a non-2xx poll response (auth expiry,
  429, 5xx) was silently retried until a generic timeout masked the real
  error.
- app/order/[id]/page.tsx: finish() never cleared the production-simulation
  setInterval, so it kept firing (and re-rendering) forever after delivery.
- app/admin/page.tsx: the metrics fetch had no response/shape validation
  (unlike the adjacent orders fetch), rendering literal "undefined" stat
  tiles on a malformed response instead of falling back to <ErrorState/>.
- services/api/workers/pipeline.py: `config.get("seeds") or DEMO_SEEDS`
  used truthy-or, so an explicit empty seeds dict was silently replaced
  with hardcoded demo org numbers instead of being respected as empty.
- services/api/workers/resolve.py: corroboration (confidence/agreed_sources
  bump) no longer fires for two hits from the same source under fuzzy
  match -- only a genuinely independent source now counts, per docs/06's
  own ">=2 independent sources agree" definition -- and a merged record's
  provenance array now actually includes the corroborating source's
  fields instead of only a bare source-name string.
- services/api/orchestrator/main.py: create_order's int(...) on
  unvalidated client volume/confidence fields raised on any
  decimal-formatted input (int("92.5") -> ValueError); now coerced via
  float() first with a safe default. /vehicles/{plate} and /screen also
  now catch connector exceptions and degrade gracefully, matching
  pipeline.py's existing pattern for the same connectors.
- lib/orders-store.ts: postgres.js (pinned v3.4.9) returns bigint/numeric
  columns as strings by default; getOrder/listOrders/setStatus were
  silently handing callers stringified money fields. Added a narrow
  per-row coercion instead of touching the shared client's global type
  map (which would affect unrelated tables' bigint/numeric columns too).
- lib/subscriptions-store.ts: the in-memory fallback returned
  oldest-first while the Postgres branch explicitly orders newest-first;
  now consistent, mirroring the identical fix already in orders-store.ts.
- app/api/auth/login/route.ts: DEV_LOGIN_KEY was compared with a plain
  !==, a non-constant-time comparison; replaced with crypto.timingSafeEqual.

Verified before commit: tsc --noEmit clean; vitest run 88 passed, 1 todo,
0 failures (13 files, unchanged from before this commit -- no existing
test's assertions needed to change). services/api/workers/resolve.py's
source-novelty and provenance-merge logic additionally verified by direct
execution against synthetic same-source/cross-source inputs (no Python
test suite exists in this repo to add to). services/api/workers/pipeline.py
and services/api/orchestrator/main.py verified with python -m py_compile
(no httpx/fastapi installed in this environment to run them directly).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(engine): treat explicit seeds:null as missing to avoid 500 in run_job

Four-eyes follow-up to this PR's own seeds change. Switching from
`config.get('seeds') or DEMO_SEEDS` to `config['seeds'] if 'seeds' in config`
correctly stopped an explicit empty {} from being backfilled with DEMO_SEEDS,
but regressed on client-controlled `{"seeds": null}`: seeds became None and
the downstream `seeds.get(market, [])` raised AttributeError -> 500. That path
is reachable (POST /orders stores raw body.config; POST /orders/{id}/run passes
it straight to run_job). Using `config.get('seeds') is not None` keeps the
intended behaviour (explicit {} honoured, never silently seeded with demo data)
while restoring the None-tolerance the old idiom had.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* ci: add typecheck/lint/test quality gate (was deploying unguarded)

* ci: make quality gate functional — typecheck + test, drop unwired lint

The lint step ran `pnpm run lint` = `eslint .`, but eslint is not a dependency
of this repo (absent from pnpm-lock.yaml), so the step failed on command-not-found
and, since a failed step aborts the job, prevented typecheck from ever running —
a red, useless gate on every PR. Replace it with the vitest suite (`pnpm run test`,
88 passing) so the gate matches the PR's stated 'typecheck + test' intent and is
green on a clean tree. Typecheck now uses `pnpm run typecheck` (carries the
`-p tsconfig.json` the script defines). Wiring eslint is left as a separate decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
merge: unify GitHub main into Gitea main (0pt)
CI (SIAX Cloud) / quality (push) Successful in 38s
CI (SIAX Cloud) / security (push) Successful in 17s
bcf285f057
Merges github/main (6 commits: 17-bug audit fix, CI quality gate,
.env.example + .gitignore fix, missing platform clients + registry
services, docs accuracy overhaul) into gitea/main (8 commits: Iceberg
write boundary + live ST0RE verification, lakehouse mapping routes,
Waves 1-4 foundational hardening).

16 conflicts. Both sides had independently written the four
src/clients/*.ts and the two registry services, so those are combined
rather than picked:

- st0re-client.ts: GitHub's endpoint wins on evidence. POST goes to
  /v1/st0re/artifacts/register, not /v1/st0re/artifacts -- verified in
  sax3l/st0re src/api/routes/artifacts.ts, where the bare path is a
  GET-only list route. Gitea's URL normalisation, error-body text and
  mock kept.
- n0d-client.ts: field is `status`, not `state`, with N0D's real 13-state
  union -- verified in sax3l/n0d packages/schemas/n0d.job.schema.json,
  which says explicitly not to add "succeeded". Gitea's mock echo,
  URL normalisation and error-body text kept.
- cl0ud-client.ts: Gitea's fail-closed HTTP normalisation kept (a 200
  with no `decision` reads as "deny", not as a silent allow). GitHub's
  PolicyDecision/PolicyDecisionValue naming kept; PolicyResult retained
  as an alias.
- aud0-client.ts: permissive union of both input types (optional
  payload/metadata/correlation_id), GitHub's echo return, Gitea's URL
  normalisation and error-body text, plus a JSON-parse fallback so a
  successful POST with an empty body does not throw.
- dataset-service.ts / source-service.ts: GitHub's record/DTO split and
  event naming (0pt.source_created / 0pt.create_source, which the merged
  docs already reference) plus Gitea's name validation, description /
  created_by fields and actor_id derivation. List filters are the union.
- lakehouse mapping routes: GitHub's shared lakehouse-mapping-registry
  singletons (without which every write 400'd "mapping not found") AND
  Gitea's Zod parseBody validation. Both, not either.
- src/types/source.ts, src/types/dataset.ts: unions of both vocabularies;
  GitHub's `access` legal-sourcing field kept.
- .env.example: GitHub's audited inventory plus Gitea's Zitadel /
  AUTH_ENFORCE block.
- CLAUDE.md, docs/ICEBERG_WRITE_BOUNDARY.md: GitHub's corrections kept,
  Gitea's live-verification kept and marked as superseding the
  "would 400 outright" finding (Gitea had already added the required
  X-Tenant-Id/X-Actor-Id headers).
- pnpm-lock.yaml: regenerated with pnpm 9.15.9, not merged.

Also corrects CLAUDE.md's claim that the banned services/scrapers stack
was "since removed" -- the removal PR is open, not merged, and this
branch inherits that code from Gitea main. Nothing here resurrects,
extends or re-wires any of it; services/scrapers/ is byte-identical to
Gitea main.

Verified on the merged tree: typecheck (src/ + tests/) clean;
17 test files, 121 passed, 1 skipped (the realinfra test skipping
honestly on ST0RE HTTP 401), 0 failures. Gitea main baseline was the
same 121/1; GitHub main baseline could not even `pnpm install`
("packages field missing or empty") -- Gitea's pnpm-workspace.yaml fix
resolves that. Whole-repo `typecheck:app` reports 9 errors, an identical
set to Gitea main's baseline, so it is advisory in both CI workflows
rather than deleted. Lint: 16 problems, identical to Gitea baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs: stop the README reading as if the banned scraper stack were already gone
CI (SIAX Cloud) / quality (push) Successful in 39s
CI (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (pull_request) Successful in 39s
CI (SIAX Cloud) / security (pull_request) Successful in 16s
96f19aab05
An independent review of this unification branch flagged that the tree asserts the
bypass/stealth/proxy-rotation paths are 'excluded by design' while
services/scrapers/ still contains all 64 files implementing exactly that --
curl_cffi TLS impersonation, cloudscraper, Tor rotation, WAFBypass, ProxyRotator,
plus committed .pyc bytecode.

Both statements were true in their own frame: CLAUDE.md §1 is the policy, and the
code is the state. The README stated the policy in the present tense, which reads
as a description of the tree.

This adds the state next to the policy and points at PR #1, which exists to delete
the directory and has been open since 2026-07-19. docs/06-data-engine.md already
documented the arrival honestly; this brings the README in line with it.

Deliberately NOT deleting services/scrapers/ here. That is PR #1's job, and folding
a policy deletion into a history-unification merge would make both harder to
review. Recording the truth is what this merge owes; removing the code is a
separate, reviewable change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
admin added 1 commit 2026-08-09 09:29:32 +00:00
resolve: README adopts main (newer, fail-closed auth docs)
CI (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 39s
CI (SIAX Cloud) / quality (pull_request) Successful in 46s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
44e83ad1de
admin merged commit into main 2026-08-09 09:31:05 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/0pt#6