Ctrl K
ComunidadGuías…

wrangler.jsonc

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/**
 * For more details on how to configure Wrangler, refer to:
 * https://developers.cloudflare.com/workers/wrangler/configuration/
 */
{
	"$schema": "node_modules/wrangler/config-schema.json",
	"name": "reccado",
	"compatibility_date": "2026-06-30",
	"compatibility_flags": ["nodejs_compat"],
	"main": "src/server.ts",
	"observability": {
		"enabled": true
	},
	"upload_source_maps": true,
	// Production should not be reachable on the shared *.workers.dev subdomain.
	// Front public installs with a custom domain and Cloudflare Access.
	"workers_dev": false,
	"vars": {
		"MAIL_FROM_ADDRESS": "noreply@mail.example.com",
		// Mailbox Durable Objects are pinned to Cloudflare's EU jurisdiction.
		// Declared rather than assumed because workerd does not implement
		// jurisdictions, so `.dev.vars` overrides this to "none" locally and the
		// guarantee only exists in a deployed Worker. See src/lib/mailbox-stub.ts.
		"MAILBOX_JURISDICTION": "eu"
	},
	"triggers": {
		"crons": ["0 * * * *"]
	},
	"send_email": [
		{
			"name": "EMAIL"
		}
	],
	"durable_objects": {
		"bindings": [
			{
				"name": "MAILBOX_DO",
				"class_name": "MailboxDurableObject"
			}
		]
	},
	"r2_buckets": [
		{
			"binding": "MAIL_OBJECTS",
			"bucket_name": "inbox-mcp-raw",
			// Raw MIME is the actual message content at rest — more so than D1,
			// which only holds snippets — so the residency story is incomplete
			// without it. A fork that does not want EU residency changes this and
			// MAILBOX_JURISDICTION together; changing one alone leaves a half
			// guarantee, which is worse than none because it reads as done.
			"jurisdiction": "eu"
		}
	],
	"queues": {
		"producers": [
			{
				"binding": "INBOUND_EMAIL_QUEUE",
				"queue": "inbox-mcp-inbound"
			},
			{
				"binding": "EMAIL_EVENTS_QUEUE",
				"queue": "inbox-mcp-email-events"
			},
			{
				"binding": "NOTIFY_QUEUE",
				"queue": "inbox-mcp-notify"
			}
		],
		"consumers": [
			{
				"queue": "inbox-mcp-inbound",
				"dead_letter_queue": "inbox-mcp-inbound-dlq",
				"max_batch_size": 5,
				"max_batch_timeout": 2,
				"max_retries": 3
			},
			{
				"queue": "inbox-mcp-email-events",
				"dead_letter_queue": "inbox-mcp-email-events-dlq",
				"max_batch_size": 10,
				"max_batch_timeout": 2,
				"max_retries": 3
			},
			{
				"queue": "inbox-mcp-notify",
				"dead_letter_queue": "inbox-mcp-notify-dlq",
				// Telegram takes about one message per second per chat, so a large
				// batch would spend most of its invocation being rate-limited; five
				// keeps a burst moving without stalling the consumer. The 1s timeout
				// is the point of the queue — a notification that waits to fill a
				// batch is a notification that arrived late. max_retries is higher
				// than ingest's because the failures here are Telegram outages and
				// 429s, which pass, and a dropped push is a signal the operator
				// never gets back.
				"max_batch_size": 5,
				"max_batch_timeout": 1,
				"max_retries": 5
			},
			// The three dead-letter queues are consumed by the same terminal
			// tombstone handler: a dead message must land somewhere durable and
			// named instead of evaporating when Queues retention expires. These
			// entries deliberately declare no dead_letter_queue of their own —
			// this is the end of the line, and a DLQ for the DLQ would only move
			// the silence one hop away. Batches are large and unhurried because
			// nothing downstream is waiting; the retries exist only to ride out a
			// D1 blip while writing the record.
			{
				"queue": "inbox-mcp-inbound-dlq",
				"max_batch_size": 10,
				"max_batch_timeout": 5,
				"max_retries": 5
			},
			{
				"queue": "inbox-mcp-email-events-dlq",
				"max_batch_size": 10,
				"max_batch_timeout": 5,
				"max_retries": 5
			},
			{
				"queue": "inbox-mcp-notify-dlq",
				"max_batch_size": 10,
				"max_batch_timeout": 5,
				"max_retries": 5
			}
		]
	},
	"d1_databases": [
		{
			"binding": "INDEX_DB",
			"database_name": "inbox-mcp-index",
			// Forkers: create your own D1 database (`wrangler d1 create
			// inbox-mcp-index`) and paste its id here. This is a template
			// value, not a real database.
			"database_id": "<your-prod-d1-database-id>",
			"migrations_dir": "migrations/d1"
		}
	],
	"migrations": [
		{
			"tag": "v1",
			"new_sqlite_classes": ["MailboxDurableObject"]
		}
	],
	"env": {
		"dev": {
			"name": "reccado-dev",
			// Off, like production. Not for secrecy -- the perimeter is in the worker
			// now, so both hostnames were equally protected -- but because the
			// deployment learns its canonical origin from whichever host an
			// authenticated request last arrived on, and that origin is what MCP
			// tokens are bound to. A stale workers.dev tab loading one mailbox was
			// enough to silently re-point it away from the custom domain.
			"workers_dev": false,
			// Who may drive the bot is still a trust declaration a human makes — but a
			// personal Telegram user id committed to a public repository, changeable
			// only by redeploy, was a bad way to write one down. The declaration moved
			// to owner_identities in D1, made by sending `/start <pairing code>`.
			// TELEGRAM_ALLOWED_USER_IDS survives as an emergency bootstrap and is
			// deliberately not set here.
			"vars": {
				"MAIL_FROM_ADDRESS": "noreply@send.imsanti.dev",
				// imsanti.dev is the zone apex, so hello@imsanti.dev sends as itself. Ship
				// this only after `wrangler email sending list` shows imsanti.dev enabled:
				// a domain listed here that Cloudflare has not accepted makes every send from
				// that mailbox fail instead of falling back to MAIL_FROM_ADDRESS.
				"MAIL_SENDING_DOMAINS": "imsanti.dev,send.transcribo.es,transcribo.es",
				"MAILBOX_JURISDICTION": "eu"
			},
			"triggers": {
				"crons": ["0 * * * *"]
			},
			"send_email": [
				{
					"name": "EMAIL"
				}
			],
			"durable_objects": {
				"bindings": [
					{
						"name": "MAILBOX_DO",
						"class_name": "MailboxDurableObject"
					}
				]
			},
			"r2_buckets": [
				{
					"binding": "MAIL_OBJECTS",
					"bucket_name": "inbox-mcp-raw-dev-eu",
					"jurisdiction": "eu"
				}
			],
			"queues": {
				"producers": [
					{
						"binding": "INBOUND_EMAIL_QUEUE",
						"queue": "inbox-mcp-inbound-dev"
					},
					{
						"binding": "EMAIL_EVENTS_QUEUE",
						"queue": "inbox-mcp-email-events-dev"
					},
					{
						"binding": "NOTIFY_QUEUE",
						"queue": "inbox-mcp-notify-dev"
					}
				],
				"consumers": [
					{
						"queue": "inbox-mcp-inbound-dev",
						"dead_letter_queue": "inbox-mcp-inbound-dlq-dev",
						"max_batch_size": 5,
						"max_batch_timeout": 2,
						"max_retries": 3
					},
					{
						"queue": "inbox-mcp-email-events-dev",
						"dead_letter_queue": "inbox-mcp-email-events-dlq-dev",
						"max_batch_size": 10,
						"max_batch_timeout": 2,
						"max_retries": 3
					},
					{
						"queue": "inbox-mcp-notify-dev",
						"dead_letter_queue": "inbox-mcp-notify-dlq-dev",
						// Mirrors prod: small batches because Telegram is ~1 msg/s per
						// chat, a 1s timeout because a batched-up notification is a late
						// one, and more retries than ingest because 429s and outages pass
						// while a dropped push never comes back.
						"max_batch_size": 5,
						"max_batch_timeout": 1,
						"max_retries": 5
					},
					// Terminal tombstone consumers, as in prod: a dead message gets a
					// durable, named row in ops_events rather than expiring unseen.
					// No dead_letter_queue on purpose — the line ends here.
					{
						"queue": "inbox-mcp-inbound-dlq-dev",
						"max_batch_size": 10,
						"max_batch_timeout": 5,
						"max_retries": 5
					},
					{
						"queue": "inbox-mcp-email-events-dlq-dev",
						"max_batch_size": 10,
						"max_batch_timeout": 5,
						"max_retries": 5
					},
					{
						"queue": "inbox-mcp-notify-dlq-dev",
						"max_batch_size": 10,
						"max_batch_timeout": 5,
						"max_retries": 5
					}
				]
			},
			"d1_databases": [
				{
					"binding": "INDEX_DB",
					// Created with `--jurisdiction eu`, which is a property of the
					// database rather than of this binding, so there is nothing here to
					// declare and nothing to keep in sync. It is named `-eu` precisely
					// because that fact is otherwise invisible from the config.
					"database_name": "inbox-mcp-index-dev-eu",
					// Forkers: create your own dev D1 (`wrangler d1 create <name>
					// --update-config --binding INDEX_DB --env dev`) and this id gets
					// filled in for you. The all-zero UUID is a valid-format placeholder
					// (kept parseable because local `vitest` uses `environment: "dev"`);
					// remote dev deploys still need a real id.
					"database_id": "ac9f17a6-3159-4fd5-8f81-cd839d6aa043",
					"migrations_dir": "migrations/d1"
				}
			],
			"migrations": [
				{
					"tag": "v1",
					"new_sqlite_classes": ["MailboxDurableObject"]
				}
			]
		}
	}
}