docs: scheduled-discovery env + single-replica constraint; VISION gate-clock reset
homelab-integration.md gains a "Scheduled discovery" section documenting TAPIR_DISCOVERY_INTERVAL and TAPIR_FETCH_RATE and the load-bearing single-replica constraint (in-process scheduler → replicas: 1 is required; >1 double-runs discovery). VISION Stage 0 carries a pointer to ADR-018's gate-clock reset so nothing in docs implies the window started before unprompted use was possible. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -90,6 +90,11 @@ to the next stage's ambition until the current stage's test passes.
|
|||||||
table (see infra/Tapir build) answers "returned/read in ≥2 distinct weeks" even without an
|
table (see infra/Tapir build) answers "returned/read in ≥2 distinct weeks" even without an
|
||||||
action click — the honest signal for a *reading* product. Login events accrue only from their
|
action click — the honest signal for a *reading* product. Login events accrue only from their
|
||||||
deploy date onward, so the gate window's data begins then.
|
deploy date onward, so the gate window's data begins then.
|
||||||
|
- **Gate-clock reset (ADR-018).** The 3–4 week window starts when in-process scheduled discovery
|
||||||
|
+ auto-summarize ship — before that, unprompted use was impossible, so the prior window
|
||||||
|
measured nothing (this is starting the clock when the experiment can actually run, not a reset
|
||||||
|
to dodge a failing gate). The 2026-07-01 check-in referenced above moves accordingly to ~3–4
|
||||||
|
weeks after this deploys. See DECISIONS.md ADR-018.
|
||||||
- **This is the gate.** Hardening (Stage 1) and any SaaS ambition stay deferred until this
|
- **This is the gate.** Hardening (Stage 1) and any SaaS ambition stay deferred until this
|
||||||
behavioural signal exists. Note: multi-user machinery was deliberately built *ahead* of
|
behavioural signal exists. Note: multi-user machinery was deliberately built *ahead* of
|
||||||
this gate (ADR-012) with isolation enforced — that was an explicit, recorded call, not a
|
this gate (ADR-012) with isolation enforced — that was an explicit, recorded call, not a
|
||||||
|
|||||||
@@ -191,3 +191,23 @@ snapshot time — check brain or the live cluster before depending on them._
|
|||||||
- `user_identities(dex_subject → user_id)` table is **intentionally NOT RLS-enabled**
|
- `user_identities(dex_subject → user_id)` table is **intentionally NOT RLS-enabled**
|
||||||
(it's auth plumbing, holds no user data; data isolation is on the user-owned tables).
|
(it's auth plumbing, holds no user data; data isolation is on the user-owned tables).
|
||||||
All data access after subject resolution goes through `withUser`.
|
All data access after subject resolution goes through `withUser`.
|
||||||
|
|
||||||
|
## Scheduled discovery (ADR-018, verified 2026-06-05)
|
||||||
|
|
||||||
|
`tapir serve` runs discovery for **all users** in-process on a timer (no CronJob). Two env
|
||||||
|
knobs plus one load-bearing deployment constraint:
|
||||||
|
|
||||||
|
- `TAPIR_DISCOVERY_INTERVAL` — Go duration, e.g. `2h`. The cadence the serve process runs a
|
||||||
|
discovery pass for every registered user (run-once-on-startup, then every interval).
|
||||||
|
**Unset or `0` = disabled** (dev/tests never auto-fetch).
|
||||||
|
- `TAPIR_FETCH_RATE` — Go duration, default `2s`. The **process-wide per-egress-IP caption-fetch
|
||||||
|
rate gate** (ADR-014 item 2). Every caption fetch — scheduler runners *and* the web "Summarize"
|
||||||
|
click-path — serialises through this one limiter so the pod cannot collectively trip 429s. `0`
|
||||||
|
= unlimited (dev/tests). This is the precondition that makes auto-summarize-on-a-schedule safe;
|
||||||
|
do not raise it aggressively without watching for 429s.
|
||||||
|
- **SINGLE-REPLICA WARNING (load-bearing).** The scheduler lives in the web process, so
|
||||||
|
`replicas: 1` in the deployment manifest is load-bearing: running `tapir serve` at >1 replica
|
||||||
|
makes **every** replica run the discovery loop → every user fetched in parallel from the same
|
||||||
|
egress IP (429s + duplicate work). Do **not** scale `serve` past 1 replica without first moving
|
||||||
|
discovery to a k8s CronJob or adding leader election. The process logs a `Warn` at startup when
|
||||||
|
scheduled discovery is enabled, as a reminder.
|
||||||
|
|||||||
Reference in New Issue
Block a user