ZenServerSECURITY.MD2 matches
83| `/api/v1/tour/{id}` | GET | Displays tour information. <br> Justification: This is the entry point for a user. Critically, it also establishes a secure, temporary session context for the browser before any payment action is taken. | 1. HTTP Security Headers: Enforces HSTS and CSP to protect the transport layer. <br> 2. Secure Cookie Seeding: Sets the SESSION (httpOnly) and XSRF-TOKEN cookies to prepare for CSRF protection on subsequent requests. | Seeds a stateful, CSRF-protected tab before any POST; Turnstile token will be needed for nonce |
84| `/api/v1/create-nonce` | POST | Issues a single-use, 60-second "permission slip" (nonce). <br> Justification: This acts as the primary security gate. It performs all the "heavy" validation to ensure a request is from a legitimate user, preventing bots from proceeding to the more sensitive fingerprint generation step. | 1. CSRF Protection: Validates the X-XSRF-TOKEN header against the SESSION cookie. <br> 2. Bot Detection: Verifies the cfToken from Cloudflare Turnstile. <br> 3. **Honeypot Detection**: Validates email_verify field contains exact ๐ฏ emoji. <br> 4. Rate Limiting: Applies strict IP-based limits to prevent abuse. <br> 5. **Debug Integration**: All security checks logged with correlation IDs. | Prevents bots, CSRF, honeypot traps, and brute-force; nonce limits replay window; debug provides security visibility |
85| `/api/v1/payment/exchange-nonce` | POST | Consumes a valid nonce to generate the final SHA3-512 payment fingerprint. <br> Justification: This isolates the final cryptographic step. By requiring a valid nonce, it ensures that server secrets (username/password) are only used after a request has passed all prior security checks. | 1. Nonce Validation: Checks that the provided nonce from the X-Payment-Nonce header exists, has not expired, and has not been used. <br> 2. Atomic Consumption: Uses a single database UPDATE to mark the nonce as "used", preventing race conditions and replay attacks. | Guarantees exactly one fingerprint per nonce; gateway creds never reach browser |
86| `/api/v1/payment/callback` | POST (Zenpay โ server) | Receives the server-to-server payment status confirmation from the Zenpay gateway. <br> Justification: This provides a secure, out-of-band channel to learn the transaction outcome. Since it comes directly from the gateway's server, it is the definitive source of truth and cannot be spoofed by a malicious client. | 1. Callback Authentication: Verifies the ValidationCode sent by Zenpay. The server re-computes the expected SHA3-512 hash and rejects the callback if it doesn't match, preventing fraudulent or tampered-with status updates. | Authenticates callback without custom HMAC; thwarts spoof/replay |
87116117- **Creation:** A cryptographically random nonce is created only after all Layer 2 and 3 checks pass.
118- **60-Second TTL:** The nonce is stored in the database with an `expires_at` timestamp set to 60 seconds in the future.
119- **Atomic Consumption:** The server uses a single `UPDATE ... SET used=1 WHERE nonce=? AND used=0` query to validate and consume the nonce in one step, preventing race conditions.
120
ZenServerPROBLEM.md1 match
50
51* **Platform:** The application is deployed on Val Town, a serverless Deno environment.
52* **Database:** The primary data store is SQLite.
53
54## 4. Requirements for a Successful Solution
ZenServerARCHITECTURE-SERVER.md7 matches
6566subgraph "Data & External Services"
67Database[(SQLite Database)]
68Env[Environment Config]
69Zenpay[Zenpay Gateway]
101SessionLifecycle --> MemoryCleanup
102103NonceService --> Database
104TokenService --> Database
105PaymentService --> Env
106PaymentService --> Zenpay
245- Generates cryptographically random nonces
246- Enforces strict 60-second TTL
247- Ensures single-use via atomic database updates
248- Binds nonces to user IP addresses
249- **NEW:** Debug logging for nonce generation and consumption
273## 4. Data Layer
274275### 4.1. Database Schema
276277Enhanced schema supporting debug infrastructure:
489- **Log File Management:** Automatic cleanup on server restart
490491### 7.2. Database Performance
492493- **WAL Mode:** Enables concurrent reads/writes for nonce table
508- Main entry point: `default app.fetch` export
509- Environment variable configuration
510- SQLite database with WAL mode
511- Debug log management
512
49}
5051// Initialize database tables - let errors bubble up
52await initializeTables();
53
location-feed-generatorREADME.md5 matches
27โโโ address-cache.ts # Val Town blob storage cache
2829database/
30โโโ database-schema.sql # SQLite schema and indexes
3132docs/
44โ โโโ handle-resolver.test.ts
45โ โโโ address-cache.test.ts
46โ โโโ database.test.ts
47โ โโโ spatial.test.ts
48โโโ integration/ # Integration tests for API endpoints
82```
8384> **Note**: No manual database setup required! Tables are created automatically
85> when functions first run.
86136**[๐ API Documentation](docs/api-documentation.md)**
137138## ๐ Database Schema
139140The system uses 4 main SQLite tables:
118async function resolveAddressRecord(uri: string): Promise<any> {
119try {
120// Parse AT URI: at://did:plc:venue-database/community.lexicon.location.address/cafe-de-plek
121const parts = uri.replace("at://", "").split("/");
122
1// @val-town backfillCheckins
2// One-time script to backfill existing check-ins into the database
3import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
4
12try {
13// Check current stats
14console.log("๐ Current Database Stats:");
15const statsResponse = await fetch(`${ANCHOR_APPVIEW}/stats`);
16if (statsResponse.ok) {
20// Analyze the stats
21if (stats.totalCheckins === 0) {
22console.log("\nโ No check-ins found in database");
23console.log("This means either:");
24console.log(" 1. Jetstream poller hasn't run yet");
1#!/usr/bin/env node
2/**
3* Backfill existing check-ins from PDS into the feed generator database
4* This script fetches existing check-ins and processes them as if they came through Jetstream
5*/
38}
3940async function importCheckinToDatabase(record: ATProtoRecord): Promise<boolean> {
41// Extract the rkey from the URI
42const uriParts = record.uri.split('/');
56console.log(`๐ Importing check-in: "${checkinData.text || 'No message'}" (${rkey})`);
57
58// Simulate the database insert that the Jetstream poller would do
59const importData = {
60id: rkey,
70};
7172// Since we can't directly access the Val Town SQLite database from here,
73// we'll create the SQL statements that would need to be run
74const insertSQL = `
108const scriptContent = `
109// @val-town backfillCheckins
110// One-time script to backfill existing check-ins into the database
111import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
112305const record = checkins[i];
306console.log(`๐ Processing check-in ${i + 1}/${checkins.length}:`);
307await importCheckinToDatabase(record);
308}
309313console.log("๐ Summary:");
314console.log(` Check-ins found: ${checkins.length}`);
315console.log(` Ready for import to Val Town database`);
316console.log();
317console.log("๐ฏ Next steps:");
318console.log("1. Deploy the generated backfill script to Val Town");
319console.log("2. Run it once to populate the database");
320console.log("3. Check the dashboard - should show your data!");
321console.log("4. Future check-ins will be captured automatically by Jetstream");
rust-nyc-talk-submissionsindex.ts10 matches
10});
1112// Database setup
13const TABLE_NAME = "talk_submissions_3"; // Updated table name for new schema with submitter_name
1415// Initialize database
16async function initDatabase() {
17console.log(`๐พ [DB] Initializing database table: ${TABLE_NAME}`);
18await sqlite.execute(`CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
19id INTEGER PRIMARY KEY AUTOINCREMENT,
26created_at DATETIME DEFAULT CURRENT_TIMESTAMP
27)`);
28console.log(`โ [DB] Database initialization complete`);
29}
306465// Initialize DB and check environment on startup
66await initDatabase();
67const discordConfigured = checkDiscordEnvironment();
68console.log(`๐ [System] Talk submission system ready! Discord: ${discordConfigured ? "Enabled" : "Placeholder mode"}`);
109}
110111console.log(`๐พ [API] Inserting submission into database`);
112113// Insert submission into database
114const result = await sqlite.execute(
115`INSERT INTO ${TABLE_NAME} (speaker_name, talk_context, is_on_behalf, submitter_name) VALUES (?, ?, ?, ?)`,
118119const submissionId = Number(result.lastInsertRowid);
120console.log(`โ [API] Database insertion successful, submission ID: ${submissionId}`);
121122// Discord integration workflow
135await postToOrganizersChannel(speakerName, talkContext, isOnBehalf, submitterName, discordChannelId);
136137console.log(`๐พ [API] Updating database with Discord information`);
138139// Update submission with Discord info