web-agent-bridge 3.3.0 → 3.8.1
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/LICENSE +84 -72
- package/README.ar.md +1563 -1286
- package/README.md +137 -1764
- package/bin/agent-runner.js +474 -474
- package/bin/cli.js +237 -237
- package/bin/wab-init.js +244 -0
- package/bin/wab.js +80 -80
- package/examples/azure-dns-wab.js +83 -0
- package/examples/bidi-agent.js +119 -119
- package/examples/cloudflare-wab-dns.js +121 -0
- package/examples/cpanel-wab-dns.js +114 -0
- package/examples/cross-site-agent.js +91 -91
- package/examples/dns-discovery-agent.js +166 -0
- package/examples/gcp-dns-wab.js +76 -0
- package/examples/governance-agent.js +169 -0
- package/examples/mcp-agent.js +94 -94
- package/examples/next-app-router/README.md +44 -44
- package/examples/plesk-wab-dns.js +103 -0
- package/examples/puppeteer-agent.js +108 -108
- package/examples/route53-wab-dns.js +144 -0
- package/examples/saas-dashboard/README.md +55 -55
- package/examples/safe-mode-agent.js +96 -0
- package/examples/self-discovery.js +106 -0
- package/examples/shopify-hydrogen/README.md +74 -74
- package/examples/vision-agent.js +171 -171
- package/examples/wab-sign.js +74 -0
- package/examples/wab-verify.js +60 -0
- package/examples/wordpress-elementor/README.md +77 -77
- package/package.json +93 -93
- package/public/.well-known/agent-tools.json +180 -180
- package/public/.well-known/ai-assets.json +59 -59
- package/public/.well-known/security.txt +8 -8
- package/public/.well-known/wab.json +28 -0
- package/public/activate.html +448 -0
- package/public/adopt.html +236 -0
- package/public/adoption-metrics.html +188 -0
- package/public/agent-workspace.html +359 -349
- package/public/ai.html +198 -198
- package/public/api.html +397 -413
- package/public/azure-dns-integration.html +289 -0
- package/public/browser.html +486 -486
- package/public/cloudflare-integration.html +380 -0
- package/public/commander-dashboard.html +243 -243
- package/public/cookies.html +210 -210
- package/public/cpanel-integration.html +398 -0
- package/public/css/agent-workspace.css +1713 -1713
- package/public/css/premium.css +317 -317
- package/public/css/styles.css +1401 -1235
- package/public/dashboard-shieldlink.html +295 -0
- package/public/dashboard.html +711 -706
- package/public/dns.html +436 -507
- package/public/docs.html +588 -587
- package/public/enterprise-mesh.ar.html +80 -0
- package/public/enterprise-mesh.html +81 -0
- package/public/feed.xml +89 -89
- package/public/gcp-dns-integration.html +318 -0
- package/public/governance.ar.html +70 -0
- package/public/governance.html +69 -0
- package/public/growth.html +465 -463
- package/public/index.html +1372 -1070
- package/public/integrations.html +556 -556
- package/public/js/activate.js +449 -0
- package/public/js/agent-workspace.js +1740 -1740
- package/public/js/auth-nav.js +117 -31
- package/public/js/auth-redirect.js +12 -12
- package/public/js/cookie-consent.js +56 -56
- package/public/js/dns.js +438 -0
- package/public/js/wab-demo-page.js +721 -721
- package/public/js/ws-client.js +74 -74
- package/public/l-preview.html +242 -0
- package/public/llms-full.txt +360 -360
- package/public/llms.txt +125 -125
- package/public/login.html +85 -85
- package/public/mesh-dashboard.html +328 -328
- package/public/milestones.html +346 -0
- package/public/one-click.html +779 -0
- package/public/openapi.json +669 -580
- package/public/partners.ar.html +145 -0
- package/public/partners.html +143 -0
- package/public/phone-shield.html +281 -281
- package/public/plesk-integration.html +375 -0
- package/public/premium-dashboard.html +2489 -2489
- package/public/premium.html +793 -793
- package/public/privacy.html +297 -297
- package/public/provider-onboarding.html +172 -0
- package/public/provider-sandbox.html +134 -0
- package/public/providers.html +359 -0
- package/public/refusals.html +172 -0
- package/public/register.html +105 -105
- package/public/registrar-integrations.html +141 -0
- package/public/ring4.html +292 -0
- package/public/robots.txt +99 -87
- package/public/route53-integration.html +531 -0
- package/public/score.html +263 -0
- package/public/script/wab-consent.d.ts +36 -36
- package/public/script/wab-consent.js +104 -104
- package/public/script/wab-schema.js +131 -131
- package/public/script/wab.d.ts +108 -108
- package/public/script/wab.min.js +580 -580
- package/public/security.txt +8 -8
- package/public/shieldlink.html +244 -0
- package/public/shieldqr.html +231 -0
- package/public/sitemap.xml +19 -1
- package/public/terms.html +256 -256
- package/public/trust-graph-api.ar.html +92 -0
- package/public/trust-graph-api.html +91 -0
- package/public/wab-features.html +560 -0
- package/public/wab-trust.html +200 -0
- package/public/wab-truth.html +375 -0
- package/public/wab-vs-protocols.html +210 -0
- package/public/whitepaper.html +449 -0
- package/script/ai-agent-bridge.js +1754 -1754
- package/sdk/README.md +99 -99
- package/sdk/agent-mesh.js +449 -449
- package/sdk/auto-discovery.js +301 -0
- package/sdk/commander.js +262 -262
- package/sdk/governance.js +262 -0
- package/sdk/index.d.ts +464 -464
- package/sdk/index.js +649 -636
- package/sdk/multi-agent.js +318 -318
- package/sdk/package.json +2 -2
- package/sdk/safe-mode.js +221 -0
- package/sdk/safety-shield.js +219 -219
- package/sdk/schema-discovery.js +83 -83
- package/server/adapters/index.js +520 -520
- package/server/config/plans.js +412 -367
- package/server/config/secrets.js +102 -102
- package/server/control-plane/index.js +301 -301
- package/server/data-plane/index.js +354 -354
- package/server/index.js +790 -531
- package/server/llm/index.js +404 -404
- package/server/middleware/adminAuth.js +35 -35
- package/server/middleware/api-tier.js +170 -0
- package/server/middleware/auth.js +50 -50
- package/server/middleware/featureGate.js +88 -88
- package/server/middleware/rateLimits.js +100 -100
- package/server/middleware/sensitiveAction.js +157 -157
- package/server/middleware/wab-trust.js +141 -0
- package/server/migrations/001_add_analytics_indexes.sql +7 -7
- package/server/migrations/002_premium_features.sql +418 -418
- package/server/migrations/003_ads_integer_cents.sql +33 -33
- package/server/migrations/004_agent_os.sql +158 -158
- package/server/migrations/005_marketplace_metering.sql +126 -126
- package/server/migrations/006_growth_suite.sql +138 -0
- package/server/migrations/007_governance.sql +106 -0
- package/server/migrations/008_plans.sql +144 -0
- package/server/migrations/009_shieldqr.sql +30 -0
- package/server/migrations/010_extended_trust.sql +33 -0
- package/server/migrations/011_outreach.sql +47 -0
- package/server/migrations/012_shieldlink.sql +116 -0
- package/server/migrations/013_ct_monitor.sql +13 -0
- package/server/migrations/014_wab_advanced_features.sql +128 -0
- package/server/migrations/015_wab_truth_layer.sql +101 -0
- package/server/migrations/016_ring4_external_trust.sql +84 -0
- package/server/migrations/017_ring4_extensions.sql +69 -0
- package/server/migrations/018_commercial_foundations.sql +167 -0
- package/server/migrations/019_unify_tier_constraints.sql +133 -0
- package/server/models/adapters/index.js +33 -33
- package/server/models/adapters/mysql.js +183 -183
- package/server/models/adapters/postgresql.js +172 -172
- package/server/models/adapters/sqlite.js +7 -7
- package/server/models/db.js +740 -681
- package/server/observability/failure-analysis.js +337 -337
- package/server/observability/index.js +394 -394
- package/server/protocol/capabilities.js +223 -223
- package/server/protocol/index.js +243 -243
- package/server/protocol/schema.js +584 -584
- package/server/registry/certification.js +271 -271
- package/server/registry/index.js +326 -326
- package/server/routes/activate.js +478 -0
- package/server/routes/admin-outreach.js +239 -0
- package/server/routes/admin-plans.js +76 -0
- package/server/routes/admin-premium.js +674 -671
- package/server/routes/admin-shieldlink.js +137 -0
- package/server/routes/admin-shieldqr.js +90 -0
- package/server/routes/admin-trust-monitor.js +139 -0
- package/server/routes/admin.js +550 -261
- package/server/routes/adopt.js +61 -0
- package/server/routes/ads.js +130 -130
- package/server/routes/agent-workspace.js +540 -540
- package/server/routes/api-keys.js +127 -0
- package/server/routes/api.js +150 -150
- package/server/routes/auth.js +71 -71
- package/server/routes/billing.js +57 -45
- package/server/routes/commander.js +316 -316
- package/server/routes/customer-shieldlink.js +133 -0
- package/server/routes/demo-showcase.js +332 -332
- package/server/routes/demo-store.js +154 -154
- package/server/routes/diagnose.js +373 -0
- package/server/routes/discovery.js +2348 -417
- package/server/routes/enterprise-mesh.js +170 -0
- package/server/routes/gateway.js +173 -173
- package/server/routes/governance-saas.js +203 -0
- package/server/routes/governance.js +208 -0
- package/server/routes/growth.js +1048 -0
- package/server/routes/intent.js +328 -0
- package/server/routes/license.js +251 -251
- package/server/routes/mesh.js +469 -469
- package/server/routes/noscript.js +543 -543
- package/server/routes/partners.js +201 -0
- package/server/routes/plans.js +33 -0
- package/server/routes/premium-v2.js +686 -686
- package/server/routes/premium.js +724 -724
- package/server/routes/providers.js +650 -0
- package/server/routes/reputation.js +411 -0
- package/server/routes/ring4.js +885 -0
- package/server/routes/runtime.js +2148 -2148
- package/server/routes/shieldlink.js +70 -0
- package/server/routes/shieldqr.js +88 -0
- package/server/routes/sovereign.js +465 -465
- package/server/routes/truth-layer.js +670 -0
- package/server/routes/universal.js +200 -200
- package/server/routes/unsubscribe.js +51 -0
- package/server/routes/wab-api.js +850 -850
- package/server/routes/wab-cache.js +282 -0
- package/server/runtime/container-worker.js +111 -111
- package/server/runtime/container.js +448 -448
- package/server/runtime/distributed-worker.js +362 -362
- package/server/runtime/event-bus.js +210 -210
- package/server/runtime/index.js +253 -253
- package/server/runtime/queue.js +599 -599
- package/server/runtime/replay.js +666 -666
- package/server/runtime/sandbox.js +266 -266
- package/server/runtime/scheduler.js +534 -534
- package/server/runtime/session-engine.js +293 -293
- package/server/runtime/state-manager.js +188 -188
- package/server/secrets/wab-signing-key.pem +3 -0
- package/server/secrets/wab-signing-pub.pem +3 -0
- package/server/security/cross-site-redactor.js +196 -196
- package/server/security/dry-run.js +180 -180
- package/server/security/human-gate-rate-limit.js +147 -147
- package/server/security/human-gate-transports.js +178 -178
- package/server/security/human-gate.js +281 -281
- package/server/security/index.js +368 -368
- package/server/security/intent-engine.js +245 -245
- package/server/security/reward-guard.js +171 -171
- package/server/security/rollback-store.js +239 -239
- package/server/security/token-scope.js +404 -404
- package/server/security/url-policy.js +139 -139
- package/server/services/adoption-agent.js +182 -0
- package/server/services/agent-chat.js +506 -506
- package/server/services/agent-learning.js +601 -601
- package/server/services/agent-memory.js +625 -625
- package/server/services/agent-mesh.js +555 -555
- package/server/services/agent-symphony.js +717 -717
- package/server/services/agent-tasks.js +1807 -1807
- package/server/services/api-key-engine.js +292 -292
- package/server/services/cluster.js +894 -894
- package/server/services/commander.js +738 -738
- package/server/services/edge-compute.js +440 -440
- package/server/services/email.js +233 -204
- package/server/services/fairness-engine.js +409 -0
- package/server/services/fairness.js +420 -0
- package/server/services/governance.js +466 -0
- package/server/services/hosted-runtime.js +205 -205
- package/server/services/lfd.js +635 -635
- package/server/services/local-ai.js +389 -389
- package/server/services/marketplace.js +270 -270
- package/server/services/metering.js +182 -182
- package/server/services/modules/affiliate-intelligence.js +93 -93
- package/server/services/modules/agent-firewall.js +90 -90
- package/server/services/modules/bounty.js +89 -89
- package/server/services/modules/collective-bargaining.js +92 -92
- package/server/services/modules/dark-pattern.js +66 -66
- package/server/services/modules/gov-intelligence.js +45 -45
- package/server/services/modules/neural.js +55 -55
- package/server/services/modules/notary.js +49 -49
- package/server/services/modules/price-time-machine.js +86 -86
- package/server/services/modules/protocol.js +104 -104
- package/server/services/negotiation.js +439 -439
- package/server/services/outreach-agent.js +312 -0
- package/server/services/plans.js +214 -0
- package/server/services/plugins.js +771 -771
- package/server/services/premium.js +1 -1
- package/server/services/price-intelligence.js +566 -566
- package/server/services/price-shield.js +1137 -1137
- package/server/services/provider-clients.js +740 -0
- package/server/services/reputation.js +465 -465
- package/server/services/search-engine.js +357 -357
- package/server/services/security.js +513 -513
- package/server/services/self-healing.js +843 -843
- package/server/services/shieldlink.js +492 -0
- package/server/services/shieldqr.js +322 -0
- package/server/services/sovereign-shield.js +542 -542
- package/server/services/ssl-ct-monitor.js +224 -0
- package/server/services/ssl-inspector.js +42 -0
- package/server/services/ssl-monitor.js +167 -0
- package/server/services/stripe.js +206 -192
- package/server/services/swarm.js +788 -788
- package/server/services/universal-scraper.js +662 -662
- package/server/services/verification.js +481 -481
- package/server/services/vision.js +1163 -1163
- package/server/services/wab-crypto.js +178 -0
- package/server/utils/cache.js +125 -125
- package/server/utils/migrate.js +81 -81
- package/server/utils/safe-fetch.js +228 -228
- package/server/utils/secureFields.js +50 -50
- package/server/ws.js +161 -161
- package/templates/artisan-marketplace.yaml +104 -104
- package/templates/book-price-scout.yaml +98 -98
- package/templates/electronics-price-tracker.yaml +108 -108
- package/templates/flight-deal-hunter.yaml +113 -113
- package/templates/freelancer-direct.yaml +116 -116
- package/templates/grocery-price-compare.yaml +93 -93
- package/templates/hotel-direct-booking.yaml +113 -113
- package/templates/local-services.yaml +98 -98
- package/templates/olive-oil-tunisia.yaml +88 -88
- package/templates/organic-farm-fresh.yaml +101 -101
- package/templates/restaurant-direct.yaml +97 -97
- package/templates/ring4/banking-sovereign.yaml +55 -0
- package/templates/ring4/ecommerce-sovereign.yaml +58 -0
- package/templates/ring4/healthcare-sovereign.yaml +60 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>WAB DNS — Google Cloud DNS Integration</title>
|
|
7
|
+
<link rel="stylesheet" href="/css/main.css">
|
|
8
|
+
<style>
|
|
9
|
+
body { font-family: system-ui, sans-serif; background: #0f172a; color: #e2e8f0; margin: 0; padding: 0; }
|
|
10
|
+
.page { max-width: 880px; margin: 0 auto; padding: 40px 20px 80px; }
|
|
11
|
+
h1 { font-size: 1.7rem; margin-bottom: 6px; }
|
|
12
|
+
.sub { color: #94a3b8; margin-bottom: 32px; font-size: .97rem; }
|
|
13
|
+
.card { background: #1e293b; border-radius: 10px; padding: 24px; margin-bottom: 24px; }
|
|
14
|
+
h2 { font-size: 1.1rem; margin: 0 0 14px; }
|
|
15
|
+
label { display: block; font-size: .85rem; color: #94a3b8; margin-bottom: 4px; margin-top: 14px; }
|
|
16
|
+
label:first-child { margin-top: 0; }
|
|
17
|
+
input[type=text], input[type=password], textarea {
|
|
18
|
+
width: 100%; box-sizing: border-box; background: #0f172a; border: 1px solid #334155;
|
|
19
|
+
color: #e2e8f0; border-radius: 6px; padding: 9px 12px; font-size: .93rem; font-family: inherit;
|
|
20
|
+
}
|
|
21
|
+
textarea { font-family: ui-monospace, monospace; min-height: 100px; }
|
|
22
|
+
input:focus, textarea:focus { outline: 2px solid #6366f1; border-color: transparent; }
|
|
23
|
+
.row { display: flex; gap: 12px; }
|
|
24
|
+
.row > * { flex: 1; }
|
|
25
|
+
.actions { display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap; }
|
|
26
|
+
.btn { padding: 9px 20px; border-radius: 7px; border: none; cursor: pointer; font-size: .92rem; font-weight: 600; }
|
|
27
|
+
.btn:hover { opacity: .85; }
|
|
28
|
+
.btn:disabled { opacity: .45; cursor: not-allowed; }
|
|
29
|
+
.btn-enable { background: #4285f4; color: #fff; }
|
|
30
|
+
.btn-disable { background: #ef4444; color: #fff; }
|
|
31
|
+
.btn-verify { background: #6366f1; color: #fff; }
|
|
32
|
+
.btn-secondary { background: #334155; color: #e2e8f0; }
|
|
33
|
+
#statusBar { margin-top: 18px; min-height: 36px; padding: 10px 14px; border-radius: 7px; background: #0f172a; font-size: .88rem; color: #94a3b8; display: none; }
|
|
34
|
+
#statusBar.ok { display: block; color: #4ade80; border: 1px solid #166534; }
|
|
35
|
+
#statusBar.err { display: block; color: #f87171; border: 1px solid #7f1d1d; }
|
|
36
|
+
#statusBar.info { display: block; color: #93c5fd; border: 1px solid #1e3a5f; }
|
|
37
|
+
pre { background: #0f172a; border-radius: 7px; padding: 14px 16px; font-size: .82rem; color: #94a3b8; overflow-x: auto; white-space: pre-wrap; word-break: break-word; margin: 14px 0 0; }
|
|
38
|
+
code { background: #0f172a; padding: 1px 5px; border-radius: 4px; font-size: .88em; }
|
|
39
|
+
.tab-bar { display: flex; gap: 4px; margin-bottom: 14px; }
|
|
40
|
+
.tab { padding: 5px 14px; border-radius: 6px; cursor: pointer; font-size: .84rem; background: #0f172a; color: #94a3b8; border: 1px solid #334155; }
|
|
41
|
+
.tab.active { background: #6366f1; color: #fff; border-color: transparent; }
|
|
42
|
+
.tab-panel { display: none; }
|
|
43
|
+
.tab-panel.active { display: block; }
|
|
44
|
+
.step { display: flex; gap: 14px; margin-bottom: 18px; }
|
|
45
|
+
.step-num { flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; background: #334155; color: #e2e8f0; font-size: .82rem; font-weight: 700; display: flex; align-items: center; justify-content: center; }
|
|
46
|
+
.step-body { flex: 1; padding-top: 3px; }
|
|
47
|
+
.info-box { background: #0c2340; border: 1px solid #1e3a5f; border-radius: 8px; padding: 12px 16px; font-size: .87rem; color: #93c5fd; margin-bottom: 18px; }
|
|
48
|
+
a { color: #818cf8; }
|
|
49
|
+
</style>
|
|
50
|
+
</head>
|
|
51
|
+
<body>
|
|
52
|
+
<div class="page">
|
|
53
|
+
<h1>Google Cloud DNS × WAB Discovery</h1>
|
|
54
|
+
<p class="sub">
|
|
55
|
+
Enable or disable the WAB DNS Discovery TXT record on any
|
|
56
|
+
<a href="https://cloud.google.com/dns/docs/reference/rest/v1" target="_blank" rel="noopener">Cloud DNS</a> managed zone.
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<div class="info-box">
|
|
60
|
+
ℹ <strong>OAuth 2.0 Access Token required.</strong>
|
|
61
|
+
Browser SigV4-style signing isn't supported by Cloud DNS — paste a short-lived OAuth access token instead.
|
|
62
|
+
Generate one with: <code>gcloud auth print-access-token</code>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<!-- ── STEP 1: credentials ── -->
|
|
66
|
+
<div class="card">
|
|
67
|
+
<h2>1. Authentication</h2>
|
|
68
|
+
<label>OAuth 2.0 Access Token <span style="color:#64748b;font-weight:400">(short-lived, browser keeps in memory only)</span></label>
|
|
69
|
+
<input type="password" id="gcpToken" placeholder="ya29.…" autocomplete="off">
|
|
70
|
+
<p style="margin:8px 0 0;font-size:.82rem;color:#64748b">
|
|
71
|
+
Obtain via: <code>gcloud auth print-access-token</code> (with <code>roles/dns.admin</code> on the zone).
|
|
72
|
+
Token expires in ~60 minutes — re-paste if needed.
|
|
73
|
+
</p>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<!-- ── STEP 2: project + zone + domain ── -->
|
|
77
|
+
<div class="card">
|
|
78
|
+
<h2>2. Project & Zone</h2>
|
|
79
|
+
<div class="row">
|
|
80
|
+
<div>
|
|
81
|
+
<label>GCP Project ID</label>
|
|
82
|
+
<input type="text" id="gcpProject" placeholder="my-gcp-project">
|
|
83
|
+
</div>
|
|
84
|
+
<div>
|
|
85
|
+
<label>Managed Zone Name <span style="color:#64748b;font-weight:400">(not the DNS name)</span></label>
|
|
86
|
+
<input type="text" id="gcpZone" placeholder="example-com">
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
<div class="row">
|
|
90
|
+
<div>
|
|
91
|
+
<label>Domain</label>
|
|
92
|
+
<input type="text" id="gcpDomain" placeholder="example.com">
|
|
93
|
+
</div>
|
|
94
|
+
<div>
|
|
95
|
+
<label>Endpoint URL <span style="color:#64748b;font-weight:400">(blank = auto)</span></label>
|
|
96
|
+
<input type="text" id="gcpEndpoint" placeholder="https://example.com/.well-known/wab.json">
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<!-- ── STEP 3: actions ── -->
|
|
102
|
+
<div class="card">
|
|
103
|
+
<h2>3. Actions</h2>
|
|
104
|
+
<div class="actions">
|
|
105
|
+
<button class="btn btn-enable" id="btnEnable" onclick="gcpAction('enable')">✓ Enable WAB Discovery</button>
|
|
106
|
+
<button class="btn btn-disable" id="btnDisable" onclick="gcpAction('disable')">✗ Disable WAB Discovery</button>
|
|
107
|
+
<button class="btn btn-verify" id="btnVerify" onclick="gcpVerify()">⟳ Verify Status</button>
|
|
108
|
+
<button class="btn btn-secondary" onclick="window.open('/provider-sandbox','_blank')">Open Sandbox</button>
|
|
109
|
+
</div>
|
|
110
|
+
<div id="statusBar"></div>
|
|
111
|
+
<pre id="jsonOut" style="display:none"></pre>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<!-- ── HOW IT WORKS ── -->
|
|
115
|
+
<div class="card">
|
|
116
|
+
<h2>How it works</h2>
|
|
117
|
+
<div class="step"><div class="step-num">1</div><div class="step-body">Fetch WAB record template (<code>GET /api/discovery/provider/record-template</code>) for TXT value.</div></div>
|
|
118
|
+
<div class="step"><div class="step-num">2</div><div class="step-body">Look up existing <code>_wab</code> TXT in the managed zone (<code>GET …/managedZones/{zone}/rrsets</code>).</div></div>
|
|
119
|
+
<div class="step"><div class="step-num">3</div><div class="step-body">Cloud DNS uses atomic <strong>changes</strong>: <code>POST changes</code> with <code>{additions, deletions}</code>. Enable = add (+ delete old if value differs). Disable = delete.</div></div>
|
|
120
|
+
<div class="step"><div class="step-num">4</div><div class="step-body">Confirm via <code>/api/discovery/provider/status</code>. Cloud DNS propagation is typically < 60 s.</div></div>
|
|
121
|
+
</div>
|
|
122
|
+
|
|
123
|
+
<!-- ── CODE SNIPPETS ── -->
|
|
124
|
+
<div class="card">
|
|
125
|
+
<h2>Code Snippets</h2>
|
|
126
|
+
<div class="tab-bar">
|
|
127
|
+
<div class="tab active" onclick="switchTab('nodejs')">Node.js</div>
|
|
128
|
+
<div class="tab" onclick="switchTab('gcloud')">gcloud CLI</div>
|
|
129
|
+
<div class="tab" onclick="switchTab('tf')">Terraform</div>
|
|
130
|
+
</div>
|
|
131
|
+
<div id="tab-nodejs" class="tab-panel active">
|
|
132
|
+
<pre>// npm install @google-cloud/dns
|
|
133
|
+
const { DNS } = require('@google-cloud/dns');
|
|
134
|
+
const dns = new DNS({ projectId: 'my-gcp-project' });
|
|
135
|
+
|
|
136
|
+
const ZONE = 'example-com';
|
|
137
|
+
const DOMAIN = 'example.com';
|
|
138
|
+
const TXT_VAL = `"v=wab1; endpoint=https://${DOMAIN}/.well-known/wab.json"`;
|
|
139
|
+
|
|
140
|
+
const zone = dns.zone(ZONE);
|
|
141
|
+
const recordSet = zone.record('txt', { name: `_wab.${DOMAIN}.`, ttl: 3600, data: TXT_VAL });
|
|
142
|
+
|
|
143
|
+
async function enableWAB() {
|
|
144
|
+
// delete any existing _wab TXT then add new
|
|
145
|
+
const [records] = await zone.getRecords({ type: 'TXT', name: `_wab.${DOMAIN}.` });
|
|
146
|
+
if (records.length) {
|
|
147
|
+
await zone.deleteRecords(records);
|
|
148
|
+
}
|
|
149
|
+
await zone.addRecords([recordSet]);
|
|
150
|
+
console.log('WAB Discovery ENABLED');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function disableWAB() {
|
|
154
|
+
const [records] = await zone.getRecords({ type: 'TXT', name: `_wab.${DOMAIN}.` });
|
|
155
|
+
if (!records.length) return console.log('Already disabled');
|
|
156
|
+
await zone.deleteRecords(records);
|
|
157
|
+
console.log('WAB Discovery DISABLED');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
enableWAB().catch(console.error);
|
|
161
|
+
</pre>
|
|
162
|
+
</div>
|
|
163
|
+
<div id="tab-gcloud" class="tab-panel">
|
|
164
|
+
<pre># Enable: start a transaction, add record, execute
|
|
165
|
+
gcloud dns record-sets transaction start --zone=example-com
|
|
166
|
+
gcloud dns record-sets transaction add \
|
|
167
|
+
'"v=wab1; endpoint=https://example.com/.well-known/wab.json"' \
|
|
168
|
+
--name=_wab.example.com. --ttl=3600 --type=TXT --zone=example-com
|
|
169
|
+
gcloud dns record-sets transaction execute --zone=example-com
|
|
170
|
+
|
|
171
|
+
# Disable: remove the record
|
|
172
|
+
gcloud dns record-sets transaction start --zone=example-com
|
|
173
|
+
gcloud dns record-sets transaction remove \
|
|
174
|
+
'"v=wab1; endpoint=https://example.com/.well-known/wab.json"' \
|
|
175
|
+
--name=_wab.example.com. --ttl=3600 --type=TXT --zone=example-com
|
|
176
|
+
gcloud dns record-sets transaction execute --zone=example-com
|
|
177
|
+
</pre>
|
|
178
|
+
</div>
|
|
179
|
+
<div id="tab-tf" class="tab-panel">
|
|
180
|
+
<pre>resource "google_dns_record_set" "wab_discovery" {
|
|
181
|
+
managed_zone = "example-com"
|
|
182
|
+
name = "_wab.example.com."
|
|
183
|
+
type = "TXT"
|
|
184
|
+
ttl = 3600
|
|
185
|
+
rrdatas = ["\"v=wab1; endpoint=https://example.com/.well-known/wab.json\""]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
# Toggle: count = var.wab_enabled ? 1 : 0
|
|
189
|
+
</pre>
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<!-- ── IAM ── -->
|
|
194
|
+
<div class="card">
|
|
195
|
+
<h2>Minimal IAM Role</h2>
|
|
196
|
+
<p style="font-size:.85rem;color:#94a3b8;margin:0 0 10px">
|
|
197
|
+
Use a custom role with these permissions on the managed zone:
|
|
198
|
+
</p>
|
|
199
|
+
<pre>dns.changes.create
|
|
200
|
+
dns.changes.get
|
|
201
|
+
dns.resourceRecordSets.list
|
|
202
|
+
dns.resourceRecordSets.create
|
|
203
|
+
dns.resourceRecordSets.delete</pre>
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
<p style="text-align:center;margin-top:30px;font-size:.85rem;color:#475569">
|
|
207
|
+
<a href="/provider-onboarding">← Provider Onboarding</a> ·
|
|
208
|
+
<a href="/cloudflare-integration">Cloudflare</a> ·
|
|
209
|
+
<a href="/cpanel-integration">cPanel</a> ·
|
|
210
|
+
<a href="/route53-integration">Route 53</a> ·
|
|
211
|
+
<a href="/plesk-integration">Plesk</a> ·
|
|
212
|
+
<a href="/dns">DNS Discovery</a>
|
|
213
|
+
</p>
|
|
214
|
+
</div>
|
|
215
|
+
|
|
216
|
+
<script>
|
|
217
|
+
function switchTab(name) {
|
|
218
|
+
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
|
219
|
+
document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
|
|
220
|
+
document.querySelector(`#tab-${name}`).classList.add('active');
|
|
221
|
+
event.target.classList.add('active');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function setStatus(msg, type) { const b = document.getElementById('statusBar'); b.textContent = msg; b.className = type; }
|
|
225
|
+
function showJson(o) { const p = document.getElementById('jsonOut'); p.textContent = JSON.stringify(o, null, 2); p.style.display = 'block'; }
|
|
226
|
+
|
|
227
|
+
function getInputs() {
|
|
228
|
+
return {
|
|
229
|
+
token: document.getElementById('gcpToken').value.trim(),
|
|
230
|
+
project: document.getElementById('gcpProject').value.trim(),
|
|
231
|
+
zone: document.getElementById('gcpZone').value.trim(),
|
|
232
|
+
domain: document.getElementById('gcpDomain').value.trim().toLowerCase().replace(/^https?:\/\//, '').replace(/\/$/, ''),
|
|
233
|
+
ep: document.getElementById('gcpEndpoint').value.trim(),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function gcpRequest(token, method, path, body) {
|
|
238
|
+
const r = await fetch(`https://dns.googleapis.com/dns/v1${path}`, {
|
|
239
|
+
method,
|
|
240
|
+
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
241
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
242
|
+
});
|
|
243
|
+
const j = await r.json().catch(() => ({}));
|
|
244
|
+
if (!r.ok) throw new Error(`Cloud DNS ${r.status}: ${j.error && j.error.message || JSON.stringify(j).slice(0, 300)}`);
|
|
245
|
+
return j;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async function gcpAction(action) {
|
|
249
|
+
const inp = getInputs();
|
|
250
|
+
if (!inp.token) return setStatus('Please paste an OAuth access token.', 'err');
|
|
251
|
+
if (!inp.project) return setStatus('Please enter the GCP Project ID.', 'err');
|
|
252
|
+
if (!inp.zone) return setStatus('Please enter the managed zone name.', 'err');
|
|
253
|
+
if (!inp.domain) return setStatus('Please enter the domain.', 'err');
|
|
254
|
+
|
|
255
|
+
document.getElementById('btnEnable').disabled = true;
|
|
256
|
+
document.getElementById('btnDisable').disabled = true;
|
|
257
|
+
try {
|
|
258
|
+
const ep = inp.ep || `https://${inp.domain}/.well-known/wab.json`;
|
|
259
|
+
setStatus('Fetching WAB record template…', 'info');
|
|
260
|
+
const tpl = await (await fetch(`/api/discovery/provider/record-template?domain=${encodeURIComponent(inp.domain)}&endpoint=${encodeURIComponent(ep)}`)).json();
|
|
261
|
+
const rawTxt = tpl.record && tpl.record.value;
|
|
262
|
+
if (!rawTxt) throw new Error('Could not fetch WAB record template.');
|
|
263
|
+
// Cloud DNS requires double-quoted TXT value
|
|
264
|
+
const txtVal = rawTxt.startsWith('"') ? rawTxt : `"${rawTxt}"`;
|
|
265
|
+
const fqdn = `_wab.${inp.domain}.`;
|
|
266
|
+
const base = `/projects/${inp.project}/managedZones/${inp.zone}`;
|
|
267
|
+
|
|
268
|
+
setStatus('Looking up existing _wab TXT records…', 'info');
|
|
269
|
+
const list = await gcpRequest(inp.token, 'GET', `${base}/rrsets?name=${encodeURIComponent(fqdn)}&type=TXT`);
|
|
270
|
+
const existing = (list.rrsets || [])[0] || null;
|
|
271
|
+
|
|
272
|
+
if (action === 'enable') {
|
|
273
|
+
const additions = [{ name: fqdn, type: 'TXT', ttl: 3600, rrdatas: [txtVal] }];
|
|
274
|
+
const change = { additions };
|
|
275
|
+
if (existing && existing.rrdatas && existing.rrdatas[0] === txtVal) {
|
|
276
|
+
setStatus(`Record already up-to-date for ${inp.domain}. WAB Discovery is ENABLED.`, 'ok');
|
|
277
|
+
showJson({ note: 'no change needed', existing });
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (existing) change.deletions = [existing];
|
|
281
|
+
setStatus(`Submitting change to Cloud DNS (${existing ? 'replace' : 'create'})…`, 'info');
|
|
282
|
+
const out = await gcpRequest(inp.token, 'POST', `${base}/changes`, change);
|
|
283
|
+
setStatus(`✓ _wab TXT ${existing ? 'updated' : 'created'} for ${inp.domain}. Change id=${out.id}, status=${out.status}.`, 'ok');
|
|
284
|
+
showJson(out);
|
|
285
|
+
} else {
|
|
286
|
+
if (!existing) {
|
|
287
|
+
setStatus(`No _wab TXT record found for ${inp.domain} — already disabled.`, 'ok');
|
|
288
|
+
showJson({ note: 'no record found' });
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
setStatus('Submitting delete change to Cloud DNS…', 'info');
|
|
292
|
+
const out = await gcpRequest(inp.token, 'POST', `${base}/changes`, { deletions: [existing] });
|
|
293
|
+
setStatus(`✓ _wab TXT deleted for ${inp.domain}. WAB Discovery is DISABLED.`, 'ok');
|
|
294
|
+
showJson(out);
|
|
295
|
+
}
|
|
296
|
+
} catch (err) {
|
|
297
|
+
setStatus(`Error: ${err.message}`, 'err');
|
|
298
|
+
} finally {
|
|
299
|
+
document.getElementById('btnEnable').disabled = false;
|
|
300
|
+
document.getElementById('btnDisable').disabled = false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
async function gcpVerify() {
|
|
305
|
+
const { domain } = getInputs();
|
|
306
|
+
if (!domain) return setStatus('Please enter a domain.', 'err');
|
|
307
|
+
setStatus('Checking WAB status…', 'info');
|
|
308
|
+
try {
|
|
309
|
+
const j = await (await fetch(`/api/discovery/provider/status?domain=${encodeURIComponent(domain)}`)).json();
|
|
310
|
+
if (j.status === 'enabled') setStatus(`✓ ${domain} — ENABLED.`, 'ok');
|
|
311
|
+
else if (j.status === 'partial') setStatus(`⚠ ${domain} — partial.`, 'info');
|
|
312
|
+
else setStatus(`✗ ${domain} — DISABLED.`, 'err');
|
|
313
|
+
showJson(j);
|
|
314
|
+
} catch (err) { setStatus(`Verify error: ${err.message}`, 'err'); }
|
|
315
|
+
}
|
|
316
|
+
</script>
|
|
317
|
+
</body>
|
|
318
|
+
</html>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="ar" dir="rtl">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>Governance SaaS — سجلّ تدقيق قانون الذكاء الاصطناعي الأوروبي | Web Agent Bridge</title>
|
|
7
|
+
<meta name="description" content="سجلّ تدقيق متعدّد المستأجرين للوكلاء السياديين. التقاط حالات الرفض والاعتماد والتجاوزات وقرارات السياسات. تصدير متوافق مع المادة 12 من قانون الذكاء الاصطناعي الأوروبي.">
|
|
8
|
+
<link rel="canonical" href="https://www.webagentbridge.com/governance.ar.html">
|
|
9
|
+
<style>
|
|
10
|
+
:root { --bg:#0b1020; --fg:#e7ebf3; --mute:#aab3c5; --card:#121a33; --line:#1f2a4d; }
|
|
11
|
+
*{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.75 "Cairo","Segoe UI",Tahoma,sans-serif}
|
|
12
|
+
a{color:#7dd3fc}.wrap{max-width:1120px;margin:0 auto;padding:32px 20px}
|
|
13
|
+
h1{font-size:32px;margin:0 0 8px}.sub{color:var(--mute);margin:0 0 28px}
|
|
14
|
+
pre{background:#0a1230;border:1px solid var(--line);border-radius:8px;padding:14px;overflow:auto;font-size:13.5px;direction:ltr;text-align:left}
|
|
15
|
+
code{background:#0a1230;padding:1px 6px;border-radius:4px;direction:ltr;display:inline-block}
|
|
16
|
+
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px;margin:18px 0 36px}
|
|
17
|
+
.plan{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:22px}
|
|
18
|
+
.plan h3{margin:0 0 6px}.plan .p{font-size:26px;font-weight:700;margin:6px 0}
|
|
19
|
+
.plan ul{margin:10px 18px 0 0;padding:0}
|
|
20
|
+
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin:18px 0}
|
|
21
|
+
.card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px}
|
|
22
|
+
.card h4{margin:0 0 6px}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<div class="wrap">
|
|
27
|
+
<p style="margin:0 0 6px"><a href="/">← Web Agent Bridge</a> · <a href="/governance">English</a></p>
|
|
28
|
+
<h1>Governance SaaS</h1>
|
|
29
|
+
<p class="sub">سجلّ تدقيق موقَّع للإلحاق فقط (append-only) للوكلاء السياديين. كل رفض، كل تجاوز، كل حدث سياسة — يُلتقط، يُستعلَم، ويُصدَّر للامتثال.</p>
|
|
30
|
+
|
|
31
|
+
<div class="grid">
|
|
32
|
+
<div class="card"><h4>سجلّ أحداث للإلحاق فقط</h4><p>كل قرار يتّخذه وكيلك مقابل مادّة دستورية يُسجَّل. أي عبث يكسر السلسلة.</p></div>
|
|
33
|
+
<div class="card"><h4>المادة 12 من قانون الذكاء الاصطناعي الأوروبي</h4><p>تصدير JSONL بنقرة واحدة مُصمَّم لاستيعاب المدقّقين. نوافذ احتفاظ لكلّ مساحة عمل من 90 يومًا إلى 7 سنوات.</p></div>
|
|
34
|
+
<div class="card"><h4>متعدّد المستأجرين بالتصميم</h4><p>مساحات عمل بوصول حسب الدور (مالك، مدير، مراجع، مشاهد). ربط مفاتيح API لكلّ مستأجر يمنع الكتابة المتقاطعة.</p></div>
|
|
35
|
+
<div class="card"><h4>تحليلات الرفض</h4><p>صفّ حسب نوع الحدث، المادّة، الشدّة، الوكيل المصدر. شاهد أيّ الحواجز يفعَّل أكثر ولماذا.</p></div>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<h2>الخطط</h2>
|
|
39
|
+
<div class="plans">
|
|
40
|
+
<div class="plan"><h3>Team</h3><div class="p">99 € / شهر</div>
|
|
41
|
+
<ul><li>5 مقاعد · احتفاظ 90 يومًا</li><li>100 000 حدث / شهر</li><li>تصدير JSONL</li><li>دعم بالبريد</li></ul></div>
|
|
42
|
+
<div class="plan"><h3>Business</h3><div class="p">499 € / شهر</div>
|
|
43
|
+
<ul><li>25 مقعدًا · احتفاظ 365 يومًا</li><li>2 مليون حدث / شهر</li><li>لوحات تحكّم مخصّصة</li><li>دعم بأولوية</li></ul></div>
|
|
44
|
+
<div class="plan"><h3>Enterprise</h3><div class="p">من 2 500 € / شهر</div>
|
|
45
|
+
<ul><li>مقاعد غير محدودة · احتفاظ 7 سنوات</li><li>DPA + SCC + تثبيت إقليمي</li><li>عنقود مساحة عمل متخصّص</li><li>SLA + مهندس تأهيل</li></ul></div>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<h2>إدخال الأحداث</h2>
|
|
49
|
+
<pre><code>curl -X POST https://www.webagentbridge.com/api/governance-saas/workspaces/$WS/events \
|
|
50
|
+
-H "X-API-Key: $WAB_KEY" \
|
|
51
|
+
-H "Content-Type: application/json" \
|
|
52
|
+
-d '{
|
|
53
|
+
"source": "shopping-agent-v3",
|
|
54
|
+
"event_type": "refusal",
|
|
55
|
+
"severity": "medium",
|
|
56
|
+
"subject": "user:1234 / merchant:example.com",
|
|
57
|
+
"article": "constitutional.privacy.v1#3",
|
|
58
|
+
"outcome": "refused",
|
|
59
|
+
"detail": "رفض الإفصاح عن طريقة الدفع دون إعادة تأكيد المستخدم."
|
|
60
|
+
}'</code></pre>
|
|
61
|
+
|
|
62
|
+
<h2>التصدير (جاهز للمدقّقين)</h2>
|
|
63
|
+
<pre><code>curl -H "X-Workspace-Token: $WS_TOKEN" \
|
|
64
|
+
https://www.webagentbridge.com/api/governance-saas/workspaces/$WS/export \
|
|
65
|
+
> audit-trail.jsonl</code></pre>
|
|
66
|
+
|
|
67
|
+
<p style="margin-top:30px;color:var(--mute)">لفتح مساحة عمل، تواصل مع <a href="mailto:governance@webagentbridge.com">governance@webagentbridge.com</a> أو شغّل API الإدارة بـ <code>X-Admin-Token</code>.</p>
|
|
68
|
+
</div>
|
|
69
|
+
</body>
|
|
70
|
+
</html>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" dir="ltr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>Governance SaaS — EU AI Act Audit Trail | Web Agent Bridge</title>
|
|
7
|
+
<meta name="description" content="Multi-tenant audit log for sovereign AI agents. Capture refusals, approvals, overrides, and policy decisions. EU AI Act Article 12 compliant exports.">
|
|
8
|
+
<link rel="canonical" href="https://www.webagentbridge.com/governance">
|
|
9
|
+
<style>
|
|
10
|
+
:root { --bg:#0b1020; --fg:#e7ebf3; --mute:#aab3c5; --card:#121a33; --line:#1f2a4d; }
|
|
11
|
+
*{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.55 Inter,system-ui,sans-serif}
|
|
12
|
+
a{color:#7dd3fc}.wrap{max-width:1120px;margin:0 auto;padding:32px 20px}
|
|
13
|
+
h1{font-size:34px;margin:0 0 8px}.sub{color:var(--mute);margin:0 0 28px}
|
|
14
|
+
pre{background:#0a1230;border:1px solid var(--line);border-radius:8px;padding:14px;overflow:auto;font-size:13.5px}
|
|
15
|
+
code{background:#0a1230;padding:1px 6px;border-radius:4px}
|
|
16
|
+
.plans{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px;margin:18px 0 36px}
|
|
17
|
+
.plan{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:22px}
|
|
18
|
+
.plan h3{margin:0 0 6px}.plan .p{font-size:28px;font-weight:700;margin:6px 0}
|
|
19
|
+
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;margin:18px 0}
|
|
20
|
+
.card{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:16px}
|
|
21
|
+
.card h4{margin:0 0 6px}
|
|
22
|
+
</style>
|
|
23
|
+
</head>
|
|
24
|
+
<body>
|
|
25
|
+
<div class="wrap">
|
|
26
|
+
<p style="margin:0 0 6px"><a href="/">← Web Agent Bridge</a> · <a href="/governance.ar.html">العربية</a></p>
|
|
27
|
+
<h1>Governance SaaS</h1>
|
|
28
|
+
<p class="sub">An append-only, signed audit trail for sovereign AI agents. Every refusal, every override, every policy event — captured, queryable, exportable for compliance.</p>
|
|
29
|
+
|
|
30
|
+
<div class="grid">
|
|
31
|
+
<div class="card"><h4>Append-only event log</h4><p>Every decision your agent makes against a constitutional article is recorded. Tampering would break the chain.</p></div>
|
|
32
|
+
<div class="card"><h4>EU AI Act Article 12</h4><p>One-click JSONL export designed for auditor ingestion. Per-workspace retention windows from 90 days to 7 years.</p></div>
|
|
33
|
+
<div class="card"><h4>Multi-tenant by design</h4><p>Workspaces with role-based access (owner, admin, reviewer, viewer). Per-tenant API key bindings prevent cross-writes.</p></div>
|
|
34
|
+
<div class="card"><h4>Refusal analytics</h4><p>Filter by event type, article, severity, source agent. See which guardrails fire most often and why.</p></div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<h2>Plans</h2>
|
|
38
|
+
<div class="plans">
|
|
39
|
+
<div class="plan"><h3>Team</h3><div class="p">€99 / mo</div>
|
|
40
|
+
<ul><li>5 seats · 90-day retention</li><li>100 000 events / month</li><li>JSONL export</li><li>Email support</li></ul></div>
|
|
41
|
+
<div class="plan"><h3>Business</h3><div class="p">€499 / mo</div>
|
|
42
|
+
<ul><li>25 seats · 365-day retention</li><li>2 M events / month</li><li>Custom dashboards</li><li>Priority support</li></ul></div>
|
|
43
|
+
<div class="plan"><h3>Enterprise</h3><div class="p">From €2 500 / mo</div>
|
|
44
|
+
<ul><li>Unlimited seats · 7-year retention</li><li>DPA + SCC + region pinning</li><li>Dedicated workspace cluster</li><li>SLA + onboarding engineer</li></ul></div>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<h2>Ingesting events</h2>
|
|
48
|
+
<pre><code>curl -X POST https://www.webagentbridge.com/api/governance-saas/workspaces/$WS/events \
|
|
49
|
+
-H "X-API-Key: $WAB_KEY" \
|
|
50
|
+
-H "Content-Type: application/json" \
|
|
51
|
+
-d '{
|
|
52
|
+
"source": "shopping-agent-v3",
|
|
53
|
+
"event_type": "refusal",
|
|
54
|
+
"severity": "medium",
|
|
55
|
+
"subject": "user:1234 / merchant:example.com",
|
|
56
|
+
"article": "constitutional.privacy.v1#3",
|
|
57
|
+
"outcome": "refused",
|
|
58
|
+
"detail": "Refused to disclose payment method without user re-confirmation."
|
|
59
|
+
}'</code></pre>
|
|
60
|
+
|
|
61
|
+
<h2>Exporting (auditor-ready)</h2>
|
|
62
|
+
<pre><code>curl -H "X-Workspace-Token: $WS_TOKEN" \
|
|
63
|
+
https://www.webagentbridge.com/api/governance-saas/workspaces/$WS/export \
|
|
64
|
+
> audit-trail.jsonl</code></pre>
|
|
65
|
+
|
|
66
|
+
<p style="margin-top:30px;color:var(--mute)">To open a workspace, contact <a href="mailto:governance@webagentbridge.com">governance@webagentbridge.com</a> or run the admin API with <code>X-Admin-Token</code>.</p>
|
|
67
|
+
</div>
|
|
68
|
+
</body>
|
|
69
|
+
</html>
|