Task 12.1 (direction 12, wordpress), free-launch copy pass in 12.2. Connects
a WordPress site to a TETA+PI entity (api.tetapi.dev), proves domain
ownership, and displays the resulting trust badge. Launched 100% free —
premium modules are teaser-only, unlockable solely via an owner-gifted promo
code (no payment, see § Premium).
Server-side (teta-pi/api, teta-pi/web, teta-pi/mcp) is untouched — this
plugin is a pure API client using existing endpoints (docs/api.md,
docs/verification-rework.md §2 in teta-pi/infra).
Cheapest, fastest distribution channel for "prove your site is who it says it is" — WP still runs ~40% of the web. A free plugin that gets a business domain-verified in two clicks is a GTM wedge for direction 13 (autonomous GTM), which starts once the plugin + MCP listings are live.
wordpress-plugin/
├── teta-pi.php # main plugin file, bootstrap, headers
├── uninstall.php # removes options on uninstall
├── readme.txt # wp.org listing (Plugin Check requires this)
├── includes/
│ ├── class-tetapi-plugin.php # singleton bootstrap, hooks
│ ├── class-tetapi-api.php # thin HTTP client for api.tetapi.dev
│ ├── class-tetapi-settings.php # Settings > TETA+PI admin page
│ ├── class-tetapi-domain.php # .well-known rewrite + verify start/check
│ ├── class-tetapi-badge.php # shortcode + widget, cached public payload
│ └── class-tetapi-premium.php # license-key field + locked stub sections
└── assets/
├── admin.css / admin.js # settings page only, no external libs
└── badge.css # minimal badge styling, no external libs
No Composer, no build step, no JS framework — WP core APIs only
(WP_Http/wp_remote_*, Settings API, Shortcode API, Widgets API, transients
for caching). PHP 7.4+ compatible (no enums, no readonly props, no match).
- Connect — owner pastes their
pk_live_…personal API key (docs/api.mdAuth). Plugin callsGET /businesseswith that key as Bearer to list the user's owned entities, owner picks one, we storeentity_id+entity_slug+ the key (encrypted at rest via WP'sAUTH_KEYsalt, not plaintext) inwp_options. - Domain ownership — plugin adds a rewrite rule so
https://yoursite.com/.well-known/tetapi-verify.txtserves a token. Admin clicks "Verify" →POST /businesses/{id}/verify/domain/start(site's own domain, auto-detected fromhome_url()) → get back{token, dns_txt, file}→ plugin already serves the file route → click "Check" →POST /businesses/{id}/verify/domain/check→ storeverified_at+methodin options. Re-checked on demand only (no cron — server-capacity constraint, no new sustained load). - Badge —
[tetapi_badge]shortcode and a matching widget fetchGET /businesses/by-slug/{slug}/public(no auth needed, it's the public endpoint), cache the response in a transient (15 min TTL) to avoid hitting the API on every page view, and render trust_level + legal_entity disclosure + a link to the public profile (https://app.tetapi.dev/e/{slug}).
| Field | Notes |
|---|---|
API Key (pk_live_…) |
password field, validated against GET /businesses on save |
| Entity picker | populated from GET /businesses once key is valid |
| Domain verification status | none / pending / verified, with Start/Check buttons |
| Badge preview | live preview of the shortcode output |
| Redeem code (premium) | optional field, flips Tetapi_Premium::is_licensed() true when it matches a promo code hash — no payment, gift-only (§ Premium) |
Owner decision 2026-07-14: launched 100% free, zero payment code. Module
#1 ($25) and Module #2 ($52) are teased as "coming soon" in the settings page
and readme.txt; neither is for sale. The only unlock path is a promo code
the plugin owner hands out manually (e.g. as a social-media reward) — checked
locally against a SHA-256 hash in class-tetapi-premium.php, no license
server, no payment provider. Distribution/checkout mechanics for an eventual
paid launch are a direction-13 GTM decision, not built here.
- Badge style pack — 5 additional badge layouts (compact pill, card with description, footer strip, floating corner ribbon) instead of the one free default style; a color/theme picker instead of auto light/dark.
- Auto-insert placement — inject the badge automatically into header/footer/post-end via a hook, instead of requiring manual shortcode placement (free tier: shortcode + widget only).
- Multi-entity sites — connect more than one TETA+PI entity to a single WP install (e.g. an agency site listing several verified brands) — free tier is single-entity.
- WooCommerce integration — show the badge on product/checkout pages and in order emails, for stores that want to display verified-seller status at the point of purchase.
- Verification email/document nudges — admin-dashboard widget reminding the owner to also complete Business Email Control / registry verification (raises trust_level beyond domain-only), with deep links back to app.tetapi.dev.
- Priority badge refresh — shorter transient TTL (near-live trust_level) instead of the free tier's 15-minute cache.
All six are represented as disabled UI ("🔒 Module #1 — $25, coming soon")
behind class-tetapi-premium.php. Tetapi_Premium::is_licensed() stays
false by default and only flips true if the site owner enters a code
matching a hash in a hardcoded, owner-maintained list — no license-server
calls, no payment/checkout code, nothing that phones home beyond the
existing api.tetapi.dev client.
- All output escaped (
esc_html,esc_attr,esc_url), all input sanitized (sanitize_text_field,sanitize_key) and nonce-checked on every POST. - Text domain
tetapi,load_plugin_textdomain(), all strings wrapped in__()/esc_html__(). - No direct file access (
ABSPATHguard in every file). - Settings stored via Settings API (
register_setting), capability-checked (manage_options). uninstall.phpdeletes alltetapi_*options — nothing orphaned.- No
eval, no remote file inclusion, no external JS/CSS from a CDN — badge and admin assets are enqueued from the plugin's ownassets/.
- Any change to
teta-pi/api,teta-pi/web,teta-pi/mcp. - Actual premium license validation / payment processing.
- Document-upload verification (not implemented server-side yet, per
docs/verification-rework.md§2). - Cron-based auto re-verification (server capacity constraint).