@iann29/rastro 0.1.0-alpha.5 → 0.1.0-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -29
- package/agent/integration.md +17 -15
- package/agent/manifest.json +7 -5
- package/agent/manifest.schema.json +8 -5
- package/dist/client/federation.d.ts +34 -8
- package/dist/client/federation.d.ts.map +1 -1
- package/dist/client/federation.js +17 -3
- package/dist/client/federation.js.map +1 -1
- package/dist/client/index.d.ts +418 -21
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +191 -41
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +2 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +63 -7
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/affiliates.d.ts.map +1 -1
- package/dist/component/affiliates.js +6 -2
- package/dist/component/affiliates.js.map +1 -1
- package/dist/component/cardinality.d.ts.map +1 -1
- package/dist/component/cardinality.js.map +1 -1
- package/dist/component/constants.d.ts +7 -1
- package/dist/component/constants.d.ts.map +1 -1
- package/dist/component/constants.js +13 -1
- package/dist/component/constants.js.map +1 -1
- package/dist/component/diagnostics.d.ts.map +1 -1
- package/dist/component/diagnostics.js.map +1 -1
- package/dist/component/eventStore.d.ts +2 -1
- package/dist/component/eventStore.d.ts.map +1 -1
- package/dist/component/eventStore.js +13 -10
- package/dist/component/eventStore.js.map +1 -1
- package/dist/component/funnels.d.ts.map +1 -1
- package/dist/component/funnels.js +5 -3
- package/dist/component/funnels.js.map +1 -1
- package/dist/component/geo.d.ts.map +1 -1
- package/dist/component/geo.js +3 -2
- package/dist/component/geo.js.map +1 -1
- package/dist/component/goals.d.ts.map +1 -1
- package/dist/component/goals.js +8 -5
- package/dist/component/goals.js.map +1 -1
- package/dist/component/guards.d.ts.map +1 -1
- package/dist/component/guards.js.map +1 -1
- package/dist/component/http.d.ts.map +1 -1
- package/dist/component/http.js +51 -17
- package/dist/component/http.js.map +1 -1
- package/dist/component/ingest.d.ts +2 -1
- package/dist/component/ingest.d.ts.map +1 -1
- package/dist/component/ingest.js +143 -23
- package/dist/component/ingest.js.map +1 -1
- package/dist/component/live.d.ts.map +1 -1
- package/dist/component/live.js +1 -3
- package/dist/component/live.js.map +1 -1
- package/dist/component/reports.d.ts +60 -3
- package/dist/component/reports.d.ts.map +1 -1
- package/dist/component/reports.js +215 -49
- package/dist/component/reports.js.map +1 -1
- package/dist/component/retention.d.ts +4 -4
- package/dist/component/retention.d.ts.map +1 -1
- package/dist/component/retention.js +54 -22
- package/dist/component/retention.js.map +1 -1
- package/dist/component/sanitize.d.ts +11 -0
- package/dist/component/sanitize.d.ts.map +1 -1
- package/dist/component/sanitize.js +58 -11
- package/dist/component/sanitize.js.map +1 -1
- package/dist/component/schema.d.ts +47 -5
- package/dist/component/schema.js +21 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/component/sites.d.ts.map +1 -1
- package/dist/component/sites.js +6 -6
- package/dist/component/sites.js.map +1 -1
- package/dist/component/validators.d.ts +14 -9
- package/dist/component/validators.d.ts.map +1 -1
- package/dist/component/validators.js +5 -1
- package/dist/component/validators.js.map +1 -1
- package/dist/component/visitors.d.ts.map +1 -1
- package/dist/component/visitors.js.map +1 -1
- package/dist/component/vitals.d.ts +41 -0
- package/dist/component/vitals.d.ts.map +1 -0
- package/dist/component/vitals.js +115 -0
- package/dist/component/vitals.js.map +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/tracker/generated.d.ts +8 -4
- package/dist/tracker/generated.d.ts.map +1 -1
- package/dist/tracker/generated.js +8 -4
- package/dist/tracker/generated.js.map +1 -1
- package/dist/tracker/tracker.d.ts.map +1 -1
- package/dist/tracker/tracker.js +3 -1
- package/dist/tracker/tracker.js.map +1 -1
- package/dist/tracker/vitals.d.ts +10 -0
- package/dist/tracker/vitals.d.ts.map +1 -0
- package/dist/tracker/vitals.js +140 -0
- package/dist/tracker/vitals.js.map +1 -0
- package/dist/tracker.min.js +1 -1
- package/dist/vitals.min.js +1 -0
- package/docs/benchmarks/2026-08-20-realistic.md +71 -71
- package/docs/benchmarks/2026-08-21-formal-certification.md +50 -30
- package/docs/benchmarks/2026-08-30-alpha6-recertification.md +206 -0
- package/docs/upgrading.md +46 -8
- package/llms.txt +5 -1
- package/package.json +17 -3
- package/scripts/benchmark-ingest.mjs +101 -48
- package/src/component/_generated/api.ts +2 -0
- package/src/component/_generated/component.ts +69 -4
- package/src/component/affiliates.ts +20 -5
- package/src/component/cardinality.ts +8 -7
- package/src/component/constants.ts +13 -1
- package/src/component/diagnostics.ts +3 -2
- package/src/component/eventStore.ts +53 -46
- package/src/component/funnels.ts +19 -16
- package/src/component/geo.ts +16 -14
- package/src/component/goals.ts +29 -21
- package/src/component/guards.ts +3 -1
- package/src/component/http.ts +93 -54
- package/src/component/ingest.ts +320 -127
- package/src/component/live.ts +5 -4
- package/src/component/reports.ts +563 -219
- package/src/component/retention.ts +221 -98
- package/src/component/sanitize.ts +99 -29
- package/src/component/schema.ts +31 -5
- package/src/component/sites.ts +22 -11
- package/src/component/validators.ts +16 -7
- package/src/component/visitors.ts +16 -5
- package/src/component/vitals.ts +146 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Ingest recertification, 2026-08-30
|
|
2
|
+
|
|
3
|
+
This report recertifies the four workload profiles ahead of `0.1.0-alpha.6`,
|
|
4
|
+
against the same deployment and benchmark site as the
|
|
5
|
+
[2026-08-21 formal certification](2026-08-21-formal-certification.md). It is
|
|
6
|
+
engineering evidence for the tested revisions and deployment state, not a
|
|
7
|
+
production SLA.
|
|
8
|
+
|
|
9
|
+
## Environment
|
|
10
|
+
|
|
11
|
+
| Item | Value |
|
|
12
|
+
| ------------------- | ---------------------------------------------------------------- |
|
|
13
|
+
| Deployment | DEV canary `fast-finch-7454` (unchanged since 2026-08-21) |
|
|
14
|
+
| Benchmark site | `kx75pnr9wap522n0zmh4nnb4jh8cv110` (unchanged) |
|
|
15
|
+
| Lean run revision | `ba9eff1` (main before Web Vitals) |
|
|
16
|
+
| Later run revisions | Web Vitals build; component sources identical to merge `6250526` |
|
|
17
|
+
| Driver | One local Node.js process |
|
|
18
|
+
| Reconciliation | Exact run-scoped session IDs, indexed pages of 100 |
|
|
19
|
+
| GeoIP provider | Disabled |
|
|
20
|
+
| Health before runs | `ok: true` |
|
|
21
|
+
|
|
22
|
+
Since the 2026-08-21 certification the wire path gained salted daily visitor
|
|
23
|
+
keys, User-Agent bot rejection, client-hint browser detection, the federation
|
|
24
|
+
hardening, and the `vital` ingest branch (present but idle: no profile sends
|
|
25
|
+
vitals). Unlike 2026-08-21, the canary was not fresh: it accumulated the
|
|
26
|
+
battery's own multi-million-event history while the profiles ran, which is the
|
|
27
|
+
honest way most deployments look after a real day.
|
|
28
|
+
|
|
29
|
+
All certified runs used `--duration 600 --certify`, ran sequentially with at
|
|
30
|
+
least five minutes of cooldown, and had no competing local load. Two runs were
|
|
31
|
+
discarded and repeated because the local DNS resolver failed their first
|
|
32
|
+
connection wave (a client-side condition — the deployment was idle and healthy
|
|
33
|
+
each time); one more was discarded after a mid-run deploy from this same
|
|
34
|
+
machine. Discarded runs are not reported as capacity.
|
|
35
|
+
|
|
36
|
+
## Results
|
|
37
|
+
|
|
38
|
+
Meeting the 100 million stored-events/day target requires at least 1,157.41
|
|
39
|
+
stored events/second.
|
|
40
|
+
|
|
41
|
+
| Profile | Concurrency | Batch | Sessions | Accepted | Stored | Stored/s | Certified stored/day | p95 | Exact reconciliation | 100M/day target |
|
|
42
|
+
| --------- | ----------: | ----: | -------: | --------: | --------: | -------: | -------------------: | -------: | --------------------- | ---------------- |
|
|
43
|
+
| Lean | 100 | 50 | unique | 1,247,000 | 1,247,000 | 2,071 | 178,948,552 | 4,167 ms | 1,247,000 / 1,247,000 | Pass |
|
|
44
|
+
| Realistic | 75 | 50 | 4,096 | 1,039,050 | 988,995 | 1,644 | 142,036,529 | 4,953 ms | 988,995 / 988,995 | Pass |
|
|
45
|
+
| Heavy | 100 | 20 | 2,048 | 388,040 | 388,040 | 640 | 55,259,642 | 7,702 ms | 388,040 / 388,040 | **Below target** |
|
|
46
|
+
| Feature | 100 | 15 | 2,048 | — | — | — | **failed** | — | — | **Failed** |
|
|
47
|
+
|
|
48
|
+
### Lean
|
|
49
|
+
|
|
50
|
+
Certified by the harness: 24,940 requests, zero failures, duplicates, or
|
|
51
|
+
rejections; exact reconciliation. 178.95M stored events/day is 31% above the
|
|
52
|
+
2026-08-21 result (136.65M) on the same deployment — the byte-measurement reuse
|
|
53
|
+
first recertified for heavy on 2026-08-22 now shows up across the board, and the
|
|
54
|
+
new per-request work (bot check, client hints, salted visitor keys) did not cost
|
|
55
|
+
the hot path its headroom.
|
|
56
|
+
|
|
57
|
+
### Realistic
|
|
58
|
+
|
|
59
|
+
The driver's session pool was doubled to 4,096 (default 2,048) and that change
|
|
60
|
+
is part of this row's workload definition. At the current deployment speed the
|
|
61
|
+
2,048-session pool drives individual sessions past the documented 120
|
|
62
|
+
events/session/minute ingest budget, so a prior attempt lost 2 of 20,477
|
|
63
|
+
requests to `429 RATE_LIMITED` — the limiter working as documented, but not a
|
|
64
|
+
clean certification. With 4,096 sessions the run completed 20,781 requests with
|
|
65
|
+
**zero failures** of any kind.
|
|
66
|
+
|
|
67
|
+
The harness itself did not stamp this run: after the clean 600 s window, its
|
|
68
|
+
first reconciliation query lost a fetch to the local resolver
|
|
69
|
+
(`reconciliation:fetch failed`) and gave up. Reconciliation was re-run
|
|
70
|
+
immediately afterwards with the same `benchmark:reconcileSessionsPage` pages the
|
|
71
|
+
harness uses, with per-page retries:
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"runId": "3c81abe6-60cd-4b40-828f-cedf03fedd39",
|
|
76
|
+
"requested": 4096,
|
|
77
|
+
"found": 4096,
|
|
78
|
+
"stored": 988995,
|
|
79
|
+
"expectedStored": 988995
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
988,995 expected stored events (1,039,050 accepted − 50,055 heartbeats), 988,995
|
|
84
|
+
found — exact. 988,995 stored over the 601.6 s window is 1,644 stored/s, 142.04M
|
|
85
|
+
stored events/day, 17.6% above the 2026-08-21 result (120.81M).
|
|
86
|
+
|
|
87
|
+
### Heavy
|
|
88
|
+
|
|
89
|
+
Certified by the harness: 19,402 requests, zero failures, exact reconciliation,
|
|
90
|
+
1,990,190 request bytes/second under the 64 KiB body limit. 55.26M stored
|
|
91
|
+
events/day is 28% below the 2026-08-22 fresh-store recertification (76.62M). The
|
|
92
|
+
payload and validation are unchanged; the store was not. This run followed hours
|
|
93
|
+
of sustained battery load on a canary holding millions of freshly written rows,
|
|
94
|
+
where 2026-08-22 hit a much lighter store. Both numbers stand side by side:
|
|
95
|
+
76.62M remains the fresh-store ceiling, 55.26M is the same workload on a loaded
|
|
96
|
+
store. Neither is overwritten by the other without a matched-state rerun.
|
|
97
|
+
|
|
98
|
+
### Feature — certification FAILED (reproducible defect)
|
|
99
|
+
|
|
100
|
+
The feature profile (goals, funnels, and affiliate attribution all matching)
|
|
101
|
+
cannot currently be certified: a steady ~4–5% of requests fail with
|
|
102
|
+
`500 INTERNAL_ERROR` at every concurrency tried (100, 15, and 5), and each
|
|
103
|
+
failed request loses its whole batch — reconciliation of a 60 s smoke found only
|
|
104
|
+
946 of 997 run sessions, so this is data loss under load. Backend logs show OCC
|
|
105
|
+
retry exhaustion on the affiliate daily rollups, always on the same two
|
|
106
|
+
documents — the two `REPORT_ROLLUP_SHARDS` rows for the demo affiliate's day:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
[CONVEX M(ingest:ingestBatch)] Documents read from or written to the
|
|
110
|
+
"affiliateDailyRollups" table changed while this mutation was being run and on
|
|
111
|
+
every subsequent retry. Another call to this mutation changed the document
|
|
112
|
+
with ID "mh735zse9410dt27ftc8t3tv4s8deazf".
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The defect postdates alpha.3 (the 2026-08-21 feature run predates the
|
|
116
|
+
generation-1 daily rollups and passed clean at 384 stored/s) and predates the
|
|
117
|
+
Web Vitals change, whose fold path is separate. It is tracked as
|
|
118
|
+
[issue #52](https://github.com/amageweb/amage-rastro/issues/52); the fix needs
|
|
119
|
+
wider rollup sharding, rebalanced feature-report read budgets, and a
|
|
120
|
+
rollout-generation bump. Until it lands, no feature-profile capacity is claimed
|
|
121
|
+
at all — the 2026-08-21 33.22M row is historical evidence for alpha.3 only.
|
|
122
|
+
|
|
123
|
+
## Certified run JSON
|
|
124
|
+
|
|
125
|
+
### Lean (`cert-lean-alpha5`, run `862673e3-ff44-492e-a078-5d8c33f70101`)
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"requests": { "started": 24940, "completed": 24940, "failures": 0 },
|
|
130
|
+
"events": {
|
|
131
|
+
"sent": 1247000,
|
|
132
|
+
"heartbeats": 0,
|
|
133
|
+
"accepted": 1247000,
|
|
134
|
+
"stored": 1247000,
|
|
135
|
+
"duplicates": 0,
|
|
136
|
+
"rejected": 0,
|
|
137
|
+
"failed": 0
|
|
138
|
+
},
|
|
139
|
+
"throughput": {
|
|
140
|
+
"storedEventsPerSecond": 2071,
|
|
141
|
+
"certifiedStoredEventsPerDay": 178948552,
|
|
142
|
+
"requestBytesPerSecond": 575501
|
|
143
|
+
},
|
|
144
|
+
"latencyMs": { "p50": 2156, "p95": 4167, "p99": 5925, "max": 7189 },
|
|
145
|
+
"reconciliation": {
|
|
146
|
+
"expectedStoredEvents": 1247000,
|
|
147
|
+
"storedEvents": 1247000,
|
|
148
|
+
"matches": true
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Heavy (`cert-heavy-alpha5-r2`)
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"requests": { "started": 19402, "completed": 19402, "failures": 0 },
|
|
158
|
+
"events": {
|
|
159
|
+
"sent": 388040,
|
|
160
|
+
"accepted": 388040,
|
|
161
|
+
"stored": 388040,
|
|
162
|
+
"duplicates": 0,
|
|
163
|
+
"rejected": 0,
|
|
164
|
+
"failed": 0
|
|
165
|
+
},
|
|
166
|
+
"throughput": {
|
|
167
|
+
"storedEventsPerSecond": 640,
|
|
168
|
+
"certifiedStoredEventsPerDay": 55259642,
|
|
169
|
+
"requestBytesPerSecond": 1990190
|
|
170
|
+
},
|
|
171
|
+
"latencyMs": { "p50": 2545, "p95": 7702, "p99": 10325, "max": 11220 },
|
|
172
|
+
"reconciliation": {
|
|
173
|
+
"expectedStoredEvents": 388040,
|
|
174
|
+
"storedEvents": 388040,
|
|
175
|
+
"matches": true
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Realistic (`cert-realistic-alpha5-r3-a1`, run `3c81abe6-60cd-4b40-828f-cedf03fedd39`)
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"requests": { "started": 20781, "completed": 20781, "failures": 0 },
|
|
185
|
+
"events": {
|
|
186
|
+
"sent": 1039050,
|
|
187
|
+
"heartbeats": 50055,
|
|
188
|
+
"accepted": 1039050,
|
|
189
|
+
"duplicates": 0,
|
|
190
|
+
"rejected": 0,
|
|
191
|
+
"failed": 0
|
|
192
|
+
},
|
|
193
|
+
"throughput": {
|
|
194
|
+
"eventsPerSecond": 1727,
|
|
195
|
+
"requestBytesPerSecond": 523501
|
|
196
|
+
},
|
|
197
|
+
"latencyMs": { "p50": 1790, "p95": 4953, "p99": 7096, "max": 9274 },
|
|
198
|
+
"reconciliation": "lost to a client-side DNS failure; re-run exactly, see above"
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## What still lacks certification
|
|
203
|
+
|
|
204
|
+
GeoIP with a provider enabled, trusted server-side conversions, vitals-bearing
|
|
205
|
+
traffic (the `vital` ingest branch ran idle here), and the feature profile until
|
|
206
|
+
issue #52 is fixed.
|
package/docs/upgrading.md
CHANGED
|
@@ -6,14 +6,16 @@ deployment.
|
|
|
6
6
|
|
|
7
7
|
## Release matrix
|
|
8
8
|
|
|
9
|
-
| Current state | Required path | Success condition
|
|
10
|
-
| ----------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
11
|
-
| Fresh deployment | Install the intended release directly | Component deploys and `/rastro/health` succeeds
|
|
12
|
-
| `0.1.0-alpha.0` with maintained data | Install `0.1.0-alpha.1` first and wait for staged visitor-index backfills | Every staged index reports complete before installing `alpha.2`
|
|
13
|
-
| `0.1.0-alpha.1` | Wait for staged visitor-index backfills, then install `alpha.2` | Backfills complete before active readers deploy
|
|
14
|
-
| `0.1.0-alpha.2` with legacy `events` rows | Stay on `alpha.2` and run/resume migration | Durable success plus empty source
|
|
15
|
-
| `0.1.0-alpha.3` fresh/canonical deployment | Rehearse the next alpha normally | Schema, reports, tracker, and retention checks pass
|
|
16
|
-
|
|
|
9
|
+
| Current state | Required path | Success condition |
|
|
10
|
+
| ----------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
11
|
+
| Fresh deployment | Install the intended release directly | Component deploys and `/rastro/health` succeeds |
|
|
12
|
+
| `0.1.0-alpha.0` with maintained data | Install `0.1.0-alpha.1` first and wait for staged visitor-index backfills | Every staged index reports complete before installing `alpha.2` |
|
|
13
|
+
| `0.1.0-alpha.1` | Wait for staged visitor-index backfills, then install `alpha.2` | Backfills complete before active readers deploy |
|
|
14
|
+
| `0.1.0-alpha.2` with legacy `events` rows | Stay on `alpha.2` and run/resume migration | Durable success plus empty source |
|
|
15
|
+
| `0.1.0-alpha.3` fresh/canonical deployment | Rehearse the next alpha normally | Schema, reports, tracker, and retention checks pass |
|
|
16
|
+
| `0.1.0-alpha.3` through `alpha.5` with canonical data | Install `0.1.0-alpha.6` directly; Web Vitals tables are additive | Schema deploys and `/rastro/health` reports `webVitals: "optIn"` |
|
|
17
|
+
| `0.1.0-alpha.6` | Install `0.1.0-alpha.7` directly; no schema change | `GET /rastro/tracker.js` contains `sentAt` |
|
|
18
|
+
| Any release whose packed declarations lack federation | Stop and request an eligible exact registry release | Packed declarations contain the federation exports |
|
|
17
19
|
|
|
18
20
|
Do not upgrade a populated legacy deployment directly to a release that removes
|
|
19
21
|
the `events` table. Schema acceptance alone does not prove that telemetry was
|
|
@@ -93,6 +95,40 @@ The visitor-time indexes on legacy and canonical telemetry follow this rule.
|
|
|
93
95
|
Check the release notes for the exact intermediate version before upgrading a
|
|
94
96
|
large deployment.
|
|
95
97
|
|
|
98
|
+
## Web Vitals (alpha.6)
|
|
99
|
+
|
|
100
|
+
`0.1.0-alpha.6` adds field Web Vitals as a purely additive upgrade: a new
|
|
101
|
+
`vitalRollups` component table, the `vital` event type, the `vitalsReport`
|
|
102
|
+
query, the retention kind `vitalRollups` (governed by `reportsDays`), and the
|
|
103
|
+
pre-gzipped `GET /rastro/vitals.js` module. No data migration and no staged
|
|
104
|
+
indexes are involved — install and deploy through the host's normal workflow.
|
|
105
|
+
|
|
106
|
+
Measurement is opt-in per page. Nothing reports until the host adds the second
|
|
107
|
+
script tag documented in the README ("Field Web Vitals (optional)"); the base
|
|
108
|
+
tracker is byte-for-byte unchanged. After deploying, the federation manifest
|
|
109
|
+
advertises the optional `vitals` capability; in the central dashboard, open
|
|
110
|
+
**Conexões** and click **Verificar novamente** on the active connection so the
|
|
111
|
+
stored capability list picks it up and the **Vitais** view replaces its upgrade
|
|
112
|
+
notice. A dashboard talking to an older host shows that notice by design — the
|
|
113
|
+
protocol-v1 baseline does not require the capability.
|
|
114
|
+
|
|
115
|
+
Acceptance for this upgrade: `/rastro/health` reports
|
|
116
|
+
`features.webVitals: "optIn"`, `GET /rastro/vitals.js` serves the module, and
|
|
117
|
+
after one real page load is hidden, `vitalsReport` shows the measurement.
|
|
118
|
+
|
|
119
|
+
## Clock alignment (alpha.7)
|
|
120
|
+
|
|
121
|
+
`0.1.0-alpha.7` changes no schema. The served `tracker.js` and `vitals.js` stamp
|
|
122
|
+
each batch with `sentAt`, and `POST /rastro/events` re-anchors a batch whose
|
|
123
|
+
sender clock is more than 30 seconds from the server's before ingestion. Live
|
|
124
|
+
presence lasts five minutes after the last event or heartbeat instead of one.
|
|
125
|
+
Browsers keep the previous tracker for at most the five-minute cache plus one
|
|
126
|
+
background revalidation; a batch without `sentAt` is ingested exactly as before.
|
|
127
|
+
|
|
128
|
+
Acceptance for this upgrade: `/rastro/health` succeeds, `GET /rastro/tracker.js`
|
|
129
|
+
contains `sentAt`, and a visitor whose device clock is minutes off appears in
|
|
130
|
+
**Ao vivo** within seconds of loading a page.
|
|
131
|
+
|
|
96
132
|
## Federation releases
|
|
97
133
|
|
|
98
134
|
Federation is additive to component telemetry but requires host tables,
|
|
@@ -120,6 +156,8 @@ control-plane issuer.
|
|
|
120
156
|
- Staged indexes completed before their readers were activated.
|
|
121
157
|
- `/rastro/health` succeeds on the HTTP-actions URL.
|
|
122
158
|
- A real tracker request is accepted from an allowed origin.
|
|
159
|
+
- When the host opts into Web Vitals: `/rastro/vitals.js` serves and
|
|
160
|
+
`vitalsReport` reflects a real page load.
|
|
123
161
|
- Protected overview, journey, goal, funnel, and affiliate reports used by the
|
|
124
162
|
host still run.
|
|
125
163
|
- Trusted conversion idempotency and currency checks still pass.
|
package/llms.txt
CHANGED
|
@@ -16,6 +16,7 @@ Do not infer federation availability from this website, a dist-tag, or a source
|
|
|
16
16
|
## Architecture
|
|
17
17
|
|
|
18
18
|
- Tracker and telemetry: browser -> customer HTTP-actions URL -> customer Rastro component.
|
|
19
|
+
- Optional field Web Vitals (alpha.6+): a second browser module at `/rastro/vitals.js` reports LCP, CLS, INP, FCP, and TTFB to the same events endpoint, into bounded daily histograms.
|
|
19
20
|
- Reactive dashboard reads: amagerastro.com browser -> customer functions URL -> `rastroFederation:*`.
|
|
20
21
|
- Control plane: account, organization, connection metadata, short-lived token issuance, and revocation.
|
|
21
22
|
- The control plane does not proxy or persist customer analytics events.
|
|
@@ -29,7 +30,7 @@ Do not infer federation availability from this website, a dist-tag, or a source
|
|
|
29
30
|
- Resolve an indexed, authoritative local grant on every federated query.
|
|
30
31
|
- Grant one through ten explicit site IDs. Never grant by owner-wide enumeration.
|
|
31
32
|
- Use the canonical module name `convex/rastroFederation.ts`.
|
|
32
|
-
- Expose only the manifest, connection status, site summaries, reports, journeys, conversions, affiliates, funnels, goals, and coverage listed in the manifest.
|
|
33
|
+
- Expose only the manifest, connection status, site summaries, reports, journeys, conversions, affiliates, funnels, goals, web vitals, and coverage listed in the manifest.
|
|
33
34
|
- Use the functions URL as JWT audience and the HTTP-actions URL for tracker ingestion.
|
|
34
35
|
- Rehearse on an explicit development target. Production changes require fresh operator consent.
|
|
35
36
|
- Validate manifest, authenticated connection status, redacted site list, real ingestion, reactive live data, and local-first revocation.
|
|
@@ -51,7 +52,9 @@ Do not infer federation availability from this website, a dist-tag, or a source
|
|
|
51
52
|
- Hourly overview maximum: 24 hours.
|
|
52
53
|
- Funnel report maximum: 90 complete UTC days.
|
|
53
54
|
- Affiliate reports require complete UTC-day boundaries.
|
|
55
|
+
- Vitals report maximum: 90 complete UTC days; `vitals` is an optional capability that hosts before `alpha.6` do not advertise.
|
|
54
56
|
- Maximum live visitors: 500.
|
|
57
|
+
- Live window: five minutes since the visitor's last event or heartbeat. `POST /rastro/events` re-anchors a batch whose `sentAt` is more than 30 seconds from server time, so a wrong device clock decides neither liveness nor hour buckets.
|
|
55
58
|
- Maximum journey events: 500.
|
|
56
59
|
- Token lifetime: 10 minutes, RS256, permission `analytics:read`.
|
|
57
60
|
|
|
@@ -63,3 +66,4 @@ Do not infer federation availability from this website, a dist-tag, or a source
|
|
|
63
66
|
- Audit retained routes, identity strategy, sessions, live location, campaigns, affiliates, conversions, custom properties, retention, and intended organization membership before granting federation; stop if their sensitivity or audience cannot be established.
|
|
64
67
|
- Overview ranges require complete UTC hour or day buckets. Manual pagination honors `numItems` and `cursor` only.
|
|
65
68
|
- `dataCoverage` echoes the authorized site ID but returns no event, visitor, or session IDs.
|
|
69
|
+
- `vitalsReport` returns p75, averages, and exact good/needs-improvement/poor counts per metric, page, and device — never individual measurements.
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"bugs": {
|
|
7
7
|
"url": "https://github.com/amageweb/amage-rastro/issues"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.7",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"federation:keys": "node ./scripts/generate-federation-keys.mjs",
|
|
38
38
|
"benchmark:ingest": "node ./scripts/benchmark-ingest.mjs",
|
|
39
39
|
"benchmark:local": "vitest run src/component/benchmark.test.ts",
|
|
40
|
+
"format:check": "prettier --check .",
|
|
40
41
|
"verify:agent-docs": "node ./scripts/verify-agent-docs.mjs",
|
|
42
|
+
"verify:skill-paths": "node ./scripts/verify-skill-paths.mjs",
|
|
41
43
|
"build:codegen": "npm run build && synapse convex codegen --component-dir ./src/component && npm run build && npm run codegen:example && synapse dev --once",
|
|
42
44
|
"codegen:example": "npm run --workspace example codegen",
|
|
43
45
|
"build:clean": "npm run build:codegen",
|
|
@@ -47,8 +49,9 @@
|
|
|
47
49
|
"test:watch": "vitest --typecheck --clearScreen false",
|
|
48
50
|
"test:debug": "vitest --inspect-brk --no-file-parallelism",
|
|
49
51
|
"test:coverage": "vitest run --coverage --coverage.reporter=text",
|
|
52
|
+
"e2e": "playwright test -c control-plane/playwright.config.ts",
|
|
50
53
|
"prepare": "npm run build",
|
|
51
|
-
"preversion": "npm run build && npm exec vite -- build control-plane && npm run test && npm run lint && npm run typecheck && npm run benchmark:local && npm run verify:agent-docs"
|
|
54
|
+
"preversion": "npm run build && VITE_CONVEX_URL=https://preflight.example.convex.cloud VITE_CONVEX_SITE_URL=https://preflight.example.convex.site npm exec vite -- build control-plane && npm run test && npm run format:check && npm run lint && npm run typecheck && npm run benchmark:local && npm run verify:agent-docs && npm run verify:skill-paths"
|
|
52
55
|
},
|
|
53
56
|
"files": [
|
|
54
57
|
"dist",
|
|
@@ -78,6 +81,7 @@
|
|
|
78
81
|
"default": "./dist/react/index.js"
|
|
79
82
|
},
|
|
80
83
|
"./tracker.js": "./dist/tracker.min.js",
|
|
84
|
+
"./vitals.js": "./dist/vitals.min.js",
|
|
81
85
|
"./test": "./src/test.ts",
|
|
82
86
|
"./_generated/component.js": {
|
|
83
87
|
"types": "./dist/component/_generated/component.d.ts"
|
|
@@ -106,12 +110,19 @@
|
|
|
106
110
|
"devDependencies": {
|
|
107
111
|
"@convex-dev/eslint-plugin": "^4.0.0",
|
|
108
112
|
"@convex-dev/static-hosting": "^0.2.1",
|
|
113
|
+
"@dicebear/core": "^9.4.3",
|
|
114
|
+
"@dicebear/lorelei": "^9.4.2",
|
|
109
115
|
"@edge-runtime/vm": "^5.0.0",
|
|
110
116
|
"@eslint/eslintrc": "^3.3.6",
|
|
111
117
|
"@eslint/js": "9.39.5",
|
|
112
118
|
"@fontsource-variable/instrument-sans": "^5.3.0",
|
|
113
119
|
"@fontsource/ibm-plex-mono": "^5.3.0",
|
|
120
|
+
"@playwright/test": "^1.62.1",
|
|
114
121
|
"@tailwindcss/vite": "^4.3.3",
|
|
122
|
+
"@testing-library/dom": "^10.4.1",
|
|
123
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
124
|
+
"@testing-library/react": "^16.3.3",
|
|
125
|
+
"@testing-library/user-event": "^14.6.6",
|
|
115
126
|
"@types/node": "^24.13.3",
|
|
116
127
|
"@types/react": "^19.2.18",
|
|
117
128
|
"@types/react-dom": "^19.2.4",
|
|
@@ -129,6 +140,7 @@
|
|
|
129
140
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
130
141
|
"eslint-plugin-react-refresh": "^0.5.3",
|
|
131
142
|
"globals": "^17.9.0",
|
|
143
|
+
"jsdom": "^30.0.1",
|
|
132
144
|
"lucide-react": "^1.32.0",
|
|
133
145
|
"maplibre-gl": "^6.4.1",
|
|
134
146
|
"pkg-pr-new": "^0.0.86",
|
|
@@ -149,7 +161,9 @@
|
|
|
149
161
|
"dependencies": {
|
|
150
162
|
"@convex-dev/better-auth": "^0.12.5",
|
|
151
163
|
"better-auth": "~1.6.15",
|
|
152
|
-
"
|
|
164
|
+
"country-flag-icons": "^1.6.20",
|
|
165
|
+
"jose": "^6.2.10",
|
|
166
|
+
"simple-icons": "^16.29.0"
|
|
153
167
|
},
|
|
154
168
|
"workspaces": [
|
|
155
169
|
"example"
|