The complete build spec for the implementing agent: worker internals, caching & invalidation, provisioning, analytics, AIVIS-side work, security, failure modes, testing, milestones, and the customer documentation set.
00 · Front matter
aivis-edge-connector — public, open source (§12): worker/, ops/ CLI code, public docs. aivis-edge-fleet — private: per-customer configs, encrypted token refs, customer runbooks. The AIVIS-side additions (§06) land in the existing private epoint-digital/aivis repo, following its conventions (createApiHandler, Zod validators, one processor per JobKind, docs/v21 update rules).https://aivis-new.dev.onepoint.ro; API reference at /api/public/v1/docs, machine spec at /api/public/v1/openapi.json. Daniel supplies an aivis_ bearer token. The endpoint returns the latest available artifact per URL.| ID | Invariant |
|---|---|
| I1 | Fail-open. Any internal error yields the origin response unmodified. |
| I2 | Bounded latency. ≈1 ms warm; hard cap (~150 ms) cold; over budget ⇒ skip-and-warm. Non-HTML untouched. |
| I3 | Parity. Identical HTML for every user agent. Never bot-conditional. |
| I4 | Additive only. Exactly one tagged script element inserted; nothing else modified or removed. |
| I5 | Secret containment. Bearer tokens live only as Worker secrets; never in pages, logs, or events. |
| I6 | Reversibility. Pause/uninstall restores the pre-connector serving path in < 60 s via route removal. |
| I7 | Zero-trust ingestion. AIVIS output is untrusted input. A fully compromised AIVIS must never achieve script execution on a customer site (§07). |
| I8 | Analytics off = zero egress. With analytics disabled, no request-derived byte leaves the customer's account toward AIVIS. |
02 · Edge worker internals
TypeScript on the Cloudflare Workers runtime, built with Wrangler. Tests run against workerd (Vitest + @cloudflare/vitest-pool-workers). One worker script serves one customer zone; multi-domain customers get one deployment per zone.
aivis-edge-connector/
worker/
src/index.ts entry — fetch handler, top-level try/catch (I1)
src/gate.ts request/response gating (W-03)
src/normalize.ts URL normalization (C-01)
src/resolve.ts cache-first schema resolution (C-*)
src/ingest.ts zero-trust validation pipeline (S-*)
src/inject.ts HTMLRewriter injection (W-05)
src/bots.ts UA registry + classifier (A-*)
src/events.ts event buffer + flush (A-*)
src/config.ts env parsing + defaults (W-02)
test/ unit + integration fixtures
ops/ provisioning CLI (§04)
docs/ exported copies of these specs
All per-customer configuration arrives as Worker vars/secrets at deploy time. No runtime config fetches in v1 (keeps the hot path self-contained; the epoch var doubles as a coarse invalidation lever, C-08).
| Var | Type | Default | Meaning |
|---|---|---|---|
AIVIS_API_BASE | string | — | e.g. https://app.aivis.example; no trailing slash; redirects are not followed (S-08) |
AIVIS_TOKEN | secret | — | Business-scoped bearer token (V-02); read-JSON-LD + write-events only |
BUSINESS_ID | string | — | Pinned tenant; payloads for other businesses are rejected (S-05) |
PRIMARY_HOST | string | — | e.g. www.allianz.de; host binding for lookups + payload checks |
ANALYTICS | on|off | off | Off ⇒ classifier and event code paths never run (I8, A-01) |
INJECT | on|off | on | Off ⇒ analytics-only mode: zero HTML mutation, worker only measures (A-07) — for composition with origin connectors such as the WordPress plugin |
CACHE_TTL_S | int | 300 | Fresh window per entry (C-04) |
SWR_S | int | 86400 | Stale-while-revalidate window (C-04) |
NEG_TTL_S | int | 300 | Negative-cache window for 404s (C-05) |
LKG_MAX_S | int | 604800 | Max age of last-known-good served on upstream failure (C-06) |
BUDGET_MS | int | 150 | Cold-path hard cap (I2) |
EPOCH | int | 1 | Participates in cache keys; bump = domain-wide invalidation (C-08) |
VERIFY_SIGNATURES | off|warn|enforce | off | Signature policy (S-06); enforce for enterprise |
AIVIS_PUBKEY | string | — | Ed25519 public key (base64) pinned at deploy; required when enforcing |
EXCLUDE_PATHS | csv | /__aivis/* | Path prefixes never touched (admin panels, APIs, etc.) |
GET; path not under EXCLUDE_PATHS; not a synthetic cache-key path (/__aivis/). Everything else: fetch(request) pass-through, zero further logic.200; Content-Type starts with text/html. Redirects, errors, JSON, assets: returned as-is. Gate on the response content type, not the request Accept header — origins lie less than clients.HEAD requests: pass through (no body to rewrite).?__aivis=off bypass injection (debug aid; the parameter is stripped before origin fetch so caches don't fragment). confirm param name with DanielOrigin fetch and schema resolution start simultaneously. The response is held until the schema promise settles or BUDGET_MS elapses — whichever is first. Warm path: cache answers in ~1 ms, so the hold is unmeasurable. Cold path: at most BUDGET_MS added to TTFB, once per URL per colo per TTL. On timeout: skip injection, let waitUntil() finish the API call and populate the cache for the next request (I2).
head; insert via the element's end-tag hook so the script lands immediately before </head>. verify at build: onEndTag API shape<script type="application/ld+json" data-aivis="1" data-aivis-v="{workerVersion}">{payload}</script>. The data-aivis attribute is the idempotency + verification marker.{payload} is the sanitized re-serialization from the ingestion pipeline (S-04) — never bytes straight from the API.data-aivis (origin accidentally shipped it, or double-proxying), do not inject again. Detection via a first-pass handler on script[data-aivis].<head> element: skip injection (fragment/AMP/edge cases), count it in events as skip:no_head.skip:charset event. verify at build: rewriter charset behaviourThe entire pipeline runs inside one top-level try/catch that falls back to fetch(request). Rewriter stream errors after headers are sent are the one unfixable window — mitigated by doing all fallible work (resolution, validation) before constructing the rewriter, so the streaming phase touches no external systems. CPU-time and subrequest limits are respected by design: warm path ≈ 1 subrequest (origin only), cold path ≤ 2.
03 · Caching & invalidation
One function, shared conceptually with the API (V-07), applied to every page URL before lookup or caching:
new URL(); invalid ⇒ skip injection.https; host lowercased; default ports stripped; fragment dropped.utm_*, gclid, fbclid, msclkid, mc_eid, ref) — then, v1 default, drop the remaining query entirely (AIVIS stores canonical page URLs without queries). A per-customer keep-list can override for genuinely content-bearing params. confirm AIVIS canonical form incl. trailing-slash policy — Open Q-1Schema entries are stored in the Cloudflare cache under a synthetic URL on the customer's own zone:
cacheKey = https://{PRIMARY_HOST}/__aivis/c/{EPOCH}/{sha256(normalizedPageUrl)}
cache.delete() clears only the local colo — it is never used as an invalidation mechanism, only the purge API is (C-07).Response body is the post-validation, sanitized payload (S-04) plus metadata headers: x-aivis-generated-at, x-aivis-sig-status, x-aivis-stored-at. Cache lifetime is controlled via Cache-Control on the stored response.404 for any real visitor request under /__aivis/ — synthetic keys are cache addresses, not readable endpoints (S-09).cache.match(cacheKey). Hit & fresh ⇒ use. Hit & in SWR window ⇒ use, and revalidate via waitUntil.GET {AIVIS_API_BASE}/api/public/v1/jsonld?url={normalizedPageUrl}, bearer auth, AbortController at BUDGET_MS.200 ⇒ run ingestion pipeline (S-*) ⇒ pass ⇒ cache.put + inject. Fail ⇒ treat as upstream-invalid (C-06).404 ⇒ negative-cache marker for NEG_TTL_S (C-05); no injection.LKG_MAX_S, else skip (C-06).| State | Window | Behaviour |
|---|---|---|
| Fresh | CACHE_TTL_S (300 s) | Serve from cache, no upstream traffic |
| Stale (SWR) | SWR_S (24 h) | Serve stale, revalidate in background |
| Negative | NEG_TTL_S (300 s) | Page has no schema; don't ask again yet |
| Upstream failing | LKG_MAX_S (7 d) | Serve last-known-good — transport failures only, never after a confirmed 404 (C-10) |
| Nothing cached + failing | — | Skip injection (I1); page unaffected |
| Command | Mechanism | Propagation | Trigger |
|---|---|---|---|
| Per URL | Cloudflare single-file purge of the synthetic key | Global, seconds | Auto: AIVIS regenerate→purge hook (V-03). Manual: ops invalidate --url, later a dashboard button |
| Per domain | Batched single-file purges over the business's URL inventory (from /chains/{id}/urls), 30 files per API call | Global, seconds–minute | Manual: ops invalidate --domain. Auto candidate: chain-wide republish |
| Epoch bump | EPOCH var change + redeploy; old keys orphan and age out | Global, ~seconds (deploy) | Fallback for self-managed setups without a purge token |
purge_everything — it would flush the customer's real CDN cache (unacceptable blast radius).v1 is additive (I4). The rewriter detects pre-existing application/ld+json blocks and reports conflict:onpage_schema through events (when analytics is on) so strategists see overlap. De-duplication/replacement is explicitly a v2 conversation.
Publishing has an inverse: a bad JSON-LD must be removable, not just replaceable. Flow: unpublish in AIVIS (V-08) ⇒ /jsonld returns 404 for that URL ⇒ the purge hook (V-03) clears the edge cache key globally ⇒ the worker's next lookup gets the 404 and overwrites the cached entry — including last-known-good — with a negative marker.
Precedence rule: last-known-good exists to absorb transport failures (timeout, 5xx, network). A confirmed 404 is an authoritative statement of absence and permanently clears the LKG entry. Without this rule, a retracted schema could resurrect hours later during an API outage via the stale-if-error path — the exact opposite of a retraction. Tested explicitly (T-02).
Distinct case: removing a bad JSON-LD that the customer's own CMS ships inside the origin HTML. That is markup modification, fenced out of v1 by I4/D6, and listed as the v2 suppression/replacement conversation (C-09).
| Event | Visible on site within |
|---|---|
| JSON-LD regenerated in AIVIS (auto-purge on) | Seconds |
| Regenerated, no purge rights (self-managed, TTL-only) | ≤ CACHE_TTL_S (5 min default) |
| Manual domain invalidation | Seconds–minute |
| Retracted ("unpublished") JSON-LD gone from all pages — cannot resurrect | Seconds |
| Worker config change (epoch, settings) | Deploy time, ~seconds |
04 · Provisioning & operations
The worker always runs in the customer's Cloudflare account. The modes differ only in who holds deployment rights — which is why the Allianz handover is a permissions change, not a migration.
ops connect / deploy / verify; customer installs nothing| Scope | Level | Why |
|---|---|---|
| Workers Scripts : Edit | Account | Upload/update/delete the worker + secrets |
| Workers Routes : Edit | Zone (this zone only) | Attach/detach the route — also the kill switch (I6) |
| Zone : Read | Zone | Resolve zone ID, sanity checks |
| Cache Purge : Purge | Zone | Per-URL / per-domain invalidation (C-07) |
Exact scope names to be confirmed against the current CF token UI at build time verify at build. Token should be zone-restricted and, where the plan allows, IP-restricted to AIVIS ops egress.
| Command | Does |
|---|---|
ops connect | Verify CF token (+ scopes), resolve zone, check it matches Business.baseUrl, store encrypted in the customer config store |
ops deploy | Upload bundle, set vars + secrets, attach route {host}/*; idempotent |
ops verify | Synthetic check: fetch N live pages with cache-buster, assert exactly one data-aivis block, parse it, diff against the API's answer; check CSP headers for surprises |
ops pause / resume | Detach / re-attach the route — < 60 s, zero code path (I6) |
ops invalidate --url … | --domain | C-07 purges, with throttling + progress output |
ops uninstall | Route + script + secrets removed; prints confirmation checklist |
ops upgrade [--canary|--all] | Staged fleet rollout: internal zone → SMB cohort → enterprise; per-customer version pinning; rollback = redeploy previous bundle |
P-04 Per-customer config lives as one reviewed YAML file in the private fleet repo (aivis-edge-fleet, §12 O-01), rendered to Worker vars at deploy; secrets in an encrypted store, never in the YAML — and never anywhere in the public connector repo.
dist/) + source, wrangler.toml template, Terraform module (optional apply path)CHANGELOG.md, SHA-256SUMS + signature, provenance attestation05 · Analytics
A-01 / I8. ANALYTICS=off is the deploy-time default. When off, the classifier and event modules are never invoked and the worker makes zero requests to AIVIS beyond schema pulls — a statement sales can put in a contract, verifiable by the customer in their own Workers logs. SMB deployments flip it on; enterprise stays off unless they opt in.
{
"ts": "2026-08-06T10:31:04Z", // minute precision is enough
"host": "www.example.com",
"path": "/products/x", // normalized path only, never query strings
"bot": "GPTBot", // matched registry family, or "none"
"cat": "training|search|live|none",
"injected": true, // true | false | "origin" (block already shipped by origin, A-07)
"cache": "hit|miss|skip",
"skip": "no_head|charset|budget|no_schema|conflict:onpage_schema|null",
"wv": "1.4.2" // worker version
}
waitUntil at 25 events or 30 s. Flush failure ⇒ drop (loss-tolerant; never retry on the visitor's clock). Target loss < 5%.bots.ts as data (family, operator, category, match rule). Updates ride worker releases; an EXTRA_BOTS var allows per-customer additions without a release.ANALYTICS=local — write to a Workers Analytics Engine dataset inside the customer's account; AIVIS reads it via the CF GraphQL API with the token it already holds. Analytics without customer data ever landing on AIVIS servers — the enterprise middle path.Same table as the architecture overview §7: OpenAI (GPTBot, OAI-SearchBot, ChatGPT-User), Anthropic (ClaudeBot, Claude-SearchBot, Claude-User), Perplexity (PerplexityBot, Perplexity-User), Googlebot (note: Google-Extended is a robots directive, not a UA), Bingbot, CCBot, Bytespider, Amazonbot, Applebot, meta-externalagent, MistralAI-User, DuckAssistBot. Registry entries carry a verification hint (published IP ranges / reverse-DNS) for a later "verified bot" flag — matching alone is v1.
With INJECT=off the worker becomes a pure measurement tap: no HTMLRewriter pass, no mutation of any response — only crawler classification and batched events. This is the recommended setup when the origin already delivers the JSON-LD, e.g. a WordPress site running the AIVIS WordPress Connector behind Cloudflare: the origin-shipped block rides inside cached HTML (zero added edge latency), and the worker's idempotency detection (W-05) recognizes data-aivis and records injected:"origin". Delivery at the origin, measurement at the edge — each layer where it is truthful. WordPress-side crawler analytics is permanently excluded (WP spec §22): PHP sees only cache-miss traffic, a systematically biased sample unfit for the Monitoring SKU.
06 · AIVIS-side work package
Follow repo conventions: createApiHandler + Zod, jobs as one processor per JobKind, spec updates in docs/v21. Listed in build order:
Today's aivis_ tokens are user-scoped: a worker secret in customer infrastructure could list every business of that user. Add a token type bound to one businessId with permission flags { jsonld:read, events:write }; /jsonld and /events enforce the binding. Existing user tokens keep working for the profile/API use case.
POST /api/public/v1/events Bearer (business-scoped, events:write)
body: { workerVersion, host, events: Event[≤100] } → 202
storage: EdgeEvent (raw, 90-day retention) + EdgeEventDaily rollup (kept)
rate limit: per-token, generous (batches are small); reject >100 events/req
New model EdgeConnection { businessId, mode(A|B), zoneId, accountId, cfTokenRef(encrypted), analytics, purgeEnabled, status }. After a successful generate_jsonld job — and after a retraction (V-08) — for a URL whose business has a connection with purgeEnabled: enqueue edge_purge (new JobKind) → single-file purge of that URL's synthetic key via the CF API. Domain-level purge = same job fed by the URL inventory. Failures retry ×3 then alert; purge failure is never user-facing breakage (TTL still bounds staleness).
/jsonldToday the endpoint returns the latest artifact. With auto-purge, a bad regeneration reaches production in seconds — so add a per-business serve policy: latest (today's behaviour) or validated (only artifacts with validation.errors == 0; falls back to the previous passing artifact — requires keeping the previous artifact row instead of delete-and-recreate). Default validated for connected businesses. An explicit per-URL publish flag remains future scope.
At artifact write time, sign businessId + "\n" + url + "\n" + generatedAt + "\n" + canonicalPayload with Ed25519; store { keyId, sig, canonicalPayload } on the artifact row. /jsonld returns the canonical string verbatim plus the signature block; the worker (when VERIFY_SIGNATURES=enforce) verifies against the pinned public key and parses that exact string. Signing keys live outside the app container (KMS or at minimum an isolated env not reachable from app code paths); honest limits of this scheme are stated in §07.
Per-URL action (plus chain-level bulk) that withdraws a published JSON-LD without waiting for a replacement: set suppressedAt on the artifact — recommended over hard deletion (reversible, keeps the audit trail; the existing DELETE endpoint remains for true deletion). While suppressed, /jsonld returns 404 for that URL regardless of serve policy, and the purge hook (V-03) fires immediately. Combined with C-10 the block is off every page in seconds and cannot resurrect. Dashboard surface: an "Unpublish from edge" action next to regenerate.
GET /api/public/v1/jsonld/bulk?businessId=… — paginated ready-URL list + payload hashes; used by ops verify and future warm tooling./jsonld?url= applies the same normalization as C-01 server-side, so worker and API can never disagree about identity (resolves Open Q-1 permanently).07 · Security, tenancy & privacy
The question that shaped this section: should the worker check JSON-LD integrity so that even if AIVIS OS is hacked, Allianz is never affected? Yes — the worker treats AIVIS as hostile input. The one genuinely dangerous outcome would be a crafted payload containing </script><script>… escaping the data block and executing as JavaScript on the customer's page. The pipeline below makes that structurally impossible, and everything after it shrinks what's left.
JSON.parse or reject. No eval-anything, no lenient parsing.JSON.stringify the parsed value, then replace every < with \u003c. The output is byte-equivalent JSON-LD to any consumer, but can never contain </script>, <script, or <!-- — script-context breakout becomes impossible regardless of payload content.@type/@id/@context keys consistent with Schema.org shape; serialized size ≤ 128 KiB; nesting depth ≤ 32. Violations reject.businessId must equal BUSINESS_ID; response url host must match PRIMARY_HOST (www-equivalence configurable). A payload for another tenant or domain never gets injected — kills cross-tenant injection even if the API mixes up tenants.enforce). Ed25519 verify against the public key pinned in the customer's own deployment (V-05). The customer's account holds the trust anchor, not AIVIS's runtime.| Scenario | Worst case with this design | Why not worse |
|---|---|---|
| AIVIS app/API fully compromised, signing off | Wrong facts in structured data until detected | S-02…S-05: no code execution possible; blast bounded by purge-all + pause runbook (F-*) |
| AIVIS compromised, signing enforced, keys isolated | Stale data (attacker can't sign new payloads) | Worker rejects unsigned/invalid; serves last-known-good |
| AIVIS compromised incl. signing keys | Same as row 1 — signing adds nothing if keys fall | Stated honestly in the security pack; key isolation (KMS) is the mitigation |
| Stolen AIVIS bearer token | Attacker reads that one business's JSON-LD, writes fake events | Business-scoped read-only token (V-02); rotate + revoke |
| Stolen customer CF token (Mode A) | Worker/route tampering on that zone | Zone-restricted, least-privilege scopes (P-02); customer can revoke instantly; anomaly = verify job failing |
| MITM worker↔AIVIS | — | TLS; AIVIS_API_BASE pinned; redirects not followed (S-08) |
| Supply-chain attack on the public repo (malicious PR, compromised maintainer) | Tampered release, if all guards fail | Protected branches + required review, maintainer 2FA, secret scanning, pinned deps, signed releases + provenance (§12 O-04/O-05); customers pin versions and verify checksums before deploy |
S-09 The /__aivis/ namespace returns 404 to real visitors; synthetic keys are unguessable (hashed) and carry no secrets anyway. S-10 Events contain no personal data (A-02) — the GDPR story is "bot traffic statistics, no natural persons," and ANALYTICS=off removes even that. Data-processing summary lives in §11 Pack B.
08 · Failure modes & SLOs
| Failure | Visitor sees | Detection | Recovery |
|---|---|---|---|
| AIVIS API down / slow | Page as-is; schema from last-known-good or absent | cache:skip events spike; daily verify job | None needed — self-heals on API return (I1) |
| Malformed / hostile payload | Page as-is (pipeline rejected it) | skip + sig-status events | Fix upstream; purge; LKG covered the gap |
| Worker exception | Page as-is via top-level catch | Workers error metrics; verify job | Rollback release (P-03) |
| Purge API failing | Slightly stale schema, ≤ TTL | edge_purge job retries/alerts | TTL bounds staleness at 5 min |
| AIVIS token revoked/expired | Page as-is after LKG window | 401s in resolve; events | Rotate token, redeploy secret |
| CF token revoked (Mode A) | Nothing — serving unaffected | Ops commands fail | Re-issue with customer; or handover to Mode B |
| Origin down | Origin's own error (worker passes non-200 through untouched) | — | Customer's incident, not ours — and provably so |
| Cloudflare colo issues | CF-level behaviour; worker adds nothing | CF status | — |
BUDGET_MS + 10 ms, and ≤ 1% of requests take the cold path in steady state.F-03 Runbooks (short, in ops/runbooks/): retract a single bad JSON-LD (V-08 + purge — the scalpel, seconds); pause a customer (the hammer); purge-all for a customer; roll back a release; rotate AIVIS token; rotate CF token; "AIVIS compromise" drill = pause all Mode-A customers (route detach loop) + notify Mode-B customers to pause, then purge-all after all-clear.
09 · Testing & verification
| Layer | Covers | Key cases |
|---|---|---|
| T-01 Unit | normalize, ingest, bots, inject | Normalization table (Q-1 fixtures); XSS corpus: </script>, <script, <!--, pre-escaped unicode, 129 KiB payload, depth-33 nesting, wrong-business, wrong-host, bad signature; classifier fixtures per registry entry |
| T-02 Integration (workerd) | Full request pipeline vs mock API | Warm/cold/negative/SWR/LKG paths; budget timeout ⇒ skip-and-warm; retraction precedence: confirmed 404 clears LKG, retracted URL must not resurrect during a simulated API outage (C-10); no-head page; existing data-aivis idempotency; non-HTML/redirect/404 pass-through byte-identical (I1/I4 assertion = response diff) |
| T-03 Live smoke | Real dev API | GET /me; GET /jsonld?url=… with Daniel's token; payload passes ingestion; latency measured against budget assumptions |
| T-04 End-to-end staging | AIVIS-owned CF zone + demo site | Deploy via ops CLI; verify command green; regenerate in AIVIS ⇒ purge ⇒ page updated in seconds; unpublish in AIVIS ⇒ block gone in seconds (V-08); pause ⇒ block gone < 60 s; analytics on/off egress check (I8: capture worker subrequests, assert none to AIVIS when off) |
| T-05 Pre-customer checklist | Each onboarding | ops verify green on top-20 URLs; Google Rich Results test + Schema.org validator on 3 samples; CSP reviewed; before/after WebPageTest diff within SLO; soak 48 h on staging zone if available |
T-06 Each invariant I1–I8 must map to at least one automated test or checklist line; the mapping table lives in worker/test/INVARIANTS.md.
10 · Rollout milestones
M1–M2 and M3 can proceed in parallel after the C-01/V-07 normalization contract is agreed (Open Q-1 first).
11 · Customer documentation set
12 · Open source & supply chain
Decision (locked, D10): the connector is an open-source project on GitHub from the first commit. Rationale: the worker runs inside customer accounts anyway, so source secrecy protects nothing — while public code turns every enterprise security review into a trust asset ("audit the exact code running in your account"), makes Mode B consumption normal OSS practice, and lets the bot registry benefit from outside contributions. The moat is the AIVIS platform — graph generation, validation, monitoring — which stays private.
| Repo | Visibility | Contains |
|---|---|---|
aivis-edge-connector | public | worker/, ops/ CLI code, bot registry, public docs (O-08), examples (wrangler.toml, Terraform), CI workflows |
aivis-edge-fleet | private | Per-customer YAML configs, encrypted token references, customer runbooks, deploy automation glue, live-smoke CI with real tokens |
epoint-digital/aivis | private | The platform: Public API implementation, generation pipeline, all §06 additions, signing keys |
The rule: nothing customer-identifying and no real secrets ever enter the public repo — code, tests, fixtures, issues, commit messages, or history. Fixtures use invented domains and fake tokens. Public from the first commit means there is never a history to scrub.
Apache-2.0 (recommended; explicit patent grant, enterprise-legal-friendly — MIT is the acceptable alternative, Q-8), with NOTICE file. Contributions under DCO sign-off (no CLA — needless friction at this size). The AIVIS name and logo remain trademarks: the code is free, the brand is not; a short trademark note lives in the README.
The worker consumes a documented HTTP contract — GET /jsonld?url=… with bearer auth, the response shape from the OpenAPI spec, and the optional signature block (V-05). Any conforming backend works; AIVIS is the reference provider. This is stated openly in the public docs: the connector is generic infrastructure, the value is in what AIVIS puts through it.
CODEOWNERS, GitHub secret scanning + a gitleaks CI step, lockfile-pinned dependencies with Renovate/Dependabot.SHA-256SUMS, a signature (Sigstore/cosign or minisign — builder's choice verify at build), and GitHub artifact attestations (SLSA provenance). Mode B customers consume releases directly and verify checksums per the runbook; Mode A deploys the identical artifact via the fleet repo.README (what it does + deploy-to-your-own-zone quickstart), CONTRIBUTING.md (dev setup, DCO), SECURITY.md (private disclosure email, no public vuln issues, 72 h acknowledgement target), CODE_OF_CONDUCT.md, CHANGELOG.md.data-aivis-v version attribute on pages is acceptable disclosure; versions are public anyway.Appendix · Open questions & risks
| # | Question | Blocks | Owner |
|---|---|---|---|
| Q-1 | AIVIS canonical URL form (trailing slash, query, www) — fixes the C-01/V-07 contract | M1 | Daniel + builder |
| Q-2 | Confirm Cache API entries are single-file-purgeable on the target CF plans | M2 | Builder (spike) |
| Q-3 | Purge API rate limits per plan → domain-purge throttle values | M2 | Builder |
| Q-4 | Production hosting of AIVIS (dev is onepoint.ro) — API availability target the LKG window must absorb | M5 | Daniel |
| Q-5 | Serve-gate default (validated) — confirm with strategists; requires keeping previous artifact rows (V-04) | M3 | Daniel |
| Q-6 | Signing key custody (KMS vs isolated env) for V-05/S-07 honesty | M5 | Daniel |
| Q-7 | Human-traffic sampling in events (1:100?) or bots-only | M4 | Daniel |
| Q-8 | OSS final calls: license Apache-2.0 (recommended) vs MIT; GitHub org (epoint-digital vs a new aivis org); public project name | M1 | Daniel |