x402: flip gateway live with Viktor's wallet + Slack payment notifications

Wires the traefik stack to read two new fields from secret/viktor:
  * x402_wallet_address     -> 0xCc33BD250d39752e0ceaB616f8a05F72274a659f
  * alertmanager_slack_api_url (existing) -> reused as the per-payment
    notification webhook so payment events arrive in the same Slack
    channel as other infra alerts.

Gateway now runs `wallet_set:true, dry_run:false`. Verified end-to-end:
  - Browser UA on all 9 sites -> 200 (passes through to Anubis)
  - python-requests/2.31 + scrapy + ClaudeBot UA -> 402 with
    PaymentRequiredResponse, payTo == Viktor's wallet, amount=10000
    micro-USDC, network=base, asset=Base USDC contract
  - Direct Slack-webhook test from inside cluster -> HTTP 200

Image bumped to forgejo.../x402-gateway:d9b83125 with Slack-format
notification payload (text=..., username=x402-gateway,
icon_emoji=💰; auxiliary fields preserved for richer receivers).

Notifications fire on every successful X-PAYMENT validation; failures
on Slack webhook are logged at WARN, never block the request, never
double-charge the bot.
This commit is contained in:
Viktor 2026-05-10 18:21:37 +00:00
parent d1777d6119
commit c36858eddd
2 changed files with 25 additions and 1 deletions

View file

@ -6,6 +6,13 @@ data "vault_kv_secret_v2" "secrets" {
name = "platform"
}
# x402 wallet lives under secret/viktor (Viktor's personal config) not
# secret/platform and is the only field this stack needs from there.
data "vault_kv_secret_v2" "viktor" {
mount = "secret"
name = "viktor"
}
module "traefik" {
source = "./modules/traefik"
tier = local.tiers.core
@ -13,4 +20,8 @@ module "traefik" {
redis_host = var.redis_host
tls_secret_name = var.tls_secret_name
auth_fallback_htpasswd = data.vault_kv_secret_v2.secrets.data["auth_fallback_htpasswd"]
x402_wallet_address = lookup(data.vault_kv_secret_v2.viktor.data, "x402_wallet_address", "")
# Reuses the existing Alertmanager Slack incoming webhook same channel as
# other infra alerts. Payment events arrive as a normal Slack message.
x402_notify_webhook_url = lookup(data.vault_kv_secret_v2.viktor.data, "alertmanager_slack_api_url", "")
}

View file

@ -15,6 +15,12 @@ variable "x402_wallet_address" {
default = ""
description = "EVM wallet (Base mainnet, 0x…) that receives USDC from x402 payments. Empty = DRY_RUN, gateway always returns 200 to forwardAuth so traffic is unaffected."
}
variable "x402_notify_webhook_url" {
type = string
default = ""
description = "Slack-compatible incoming-webhook URL the gateway POSTs to on every successful payment. Empty = no notifications."
sensitive = true
}
resource "kubernetes_namespace" "traefik" {
metadata {
@ -508,7 +514,7 @@ resource "kubernetes_deployment" "x402_gateway" {
}
container {
name = "x402-gateway"
image = "forgejo.viktorbarzin.me/viktor/x402-gateway:f4804d62"
image = "forgejo.viktorbarzin.me/viktor/x402-gateway:d9b83125"
port {
name = "http"
container_port = 8923
@ -549,6 +555,13 @@ resource "kubernetes_deployment" "x402_gateway" {
name = "FACILITATOR_URL"
value = "https://x402.org/facilitator"
}
# Slack incoming-webhook for real-time payment notifications.
# Reuses the existing Alertmanager channel payment events appear
# alongside infra alerts. Reads from secret/viktor.alertmanager_slack_api_url.
env {
name = "NOTIFY_WEBHOOK_URL"
value = var.x402_notify_webhook_url
}
resources {
requests = {
cpu = "10m"