Apply demo-activity-bot: Bruno, the synthetic public-walk generator
Adds a background demo user (`bruno`) plus two pg-boss jobs that generate public trekking routes and activities in inner Berlin and prune them after 14 days. Disabled by default everywhere; flip `DEMO_BOT_ENABLED` only in prod. - Schema: `synthetic` boolean on routes + activities - `ensureDemoUser()` idempotent insert + badge on /users/bruno - Generation gate: 07-21 Berlin local, p=0.12, 40-route cap in 14d - Initial 4-walk backfill on first enable; retention via daily prune - Prometheus gauges `demo_bot_synthetic_routes_total` / `_activities_total` - Unit + DB-gated integration + E2E tests Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7304a9e904
commit
ba4c4e1b4f
16 changed files with 1003 additions and 43 deletions
|
|
@ -5,6 +5,7 @@ import {
|
|||
integer,
|
||||
real,
|
||||
jsonb,
|
||||
boolean,
|
||||
customType,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
|
|
@ -84,6 +85,12 @@ export const routes = journalSchema.table("routes", {
|
|||
tags: jsonb("tags").$type<string[]>(),
|
||||
plannerState: bytea("planner_state"),
|
||||
visibility: text("visibility").$type<Visibility>().notNull().default("private"),
|
||||
/**
|
||||
* Content generated by the demo-activity-bot. Set to true only on insert;
|
||||
* never surfaced in user-facing update flows. Lets us exclude demo content
|
||||
* from analytics and wipe all bot output with a single DELETE.
|
||||
*/
|
||||
synthetic: boolean("synthetic").notNull().default(false),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
|
@ -118,6 +125,7 @@ export const activities = journalSchema.table("activities", {
|
|||
photos: jsonb("photos").$type<string[]>(),
|
||||
participants: jsonb("participants").$type<string[]>(),
|
||||
visibility: text("visibility").$type<Visibility>().notNull().default("private"),
|
||||
synthetic: boolean("synthetic").notNull().default(false),
|
||||
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue