v1.3.0 — Commercial Hardening
Released: 2026-04-17
Commercial hardening in two waves: Core (licensing infrastructure) and Defense (anti-piracy, air-gapped tier, legal compliance). Closes licensing loopholes, adds revocation support, and prepares Forge for commercial launch.
Community Mode Restructure
Section titled “Community Mode Restructure”Community Mode is now a demonstration tier, not a free product:
- 1 repo only — the first indexed repo locks in
- 3 tools available:
forge_search(keyword only),forge_search_symbols,forge_health_check - CLI-only —
forge serve(MCP server mode) refused without a license - 100 queries/day local rate limit, resets at UTC midnight
- 10,000 file cap per repo
forge upgradeopens the pricing page; onboarding prompt on firstforge index- Anti-nag safeguard: maximum 3 upgrade prompts per day
14-Day Free Trial
Section titled “14-Day Free Trial”- Trial licenses carry a
trial: trueflag in the signed payload - Features match the selected tier at checkout — Solo trial unlocks Solo features, Pro trial unlocks Pro features
- 14 days full features; auto-converts to paid on day 15 unless cancelled
forge statusandforge licensedisplay trial badge, days remaining, and conversion date- 3-day and 1-day warnings on
forge servestartup before conversion - Email templates for trial start and trial conversion
License Health Heartbeat
Section titled “License Health Heartbeat”- Weekly (7 days ±12h jitter) POST to Cloudflare Worker
/heartbeat - Transmits only: license hash (SHA-256, not plaintext), client version, platform
- Response returns:
status(active | revoked | expired | unknown) +cached_until(14 days forward) - Cache semantics: fresh = valid; stale >30 days = warn; very stale >60 days = degrade to Community
- Spawned as a background async task from
forge serve— non-blocking - Transparent:
forge config heartbeat showdisplays the exact payload and links the privacy policy
License Revocation
Section titled “License Revocation”- Stripe
subscription.deleted→ D1status='cancelled'+revoked_attimestamp - Stripe
charge.dispute.created→ D1status='disputed' - Stripe
charge.refunded→ D1status='refunded' - Next heartbeat returns
revoked→ binary degrades to Community within one heartbeat cycle
New CLI Commands
Section titled “New CLI Commands”| Command | Description |
|---|---|
forge upgrade | Opens the pricing/trial page in the default browser |
forge deactivate | Frees the current machine’s fingerprint slot |
forge config heartbeat show | Displays exact heartbeat payload and privacy link |
forge config heartbeat now | Forces an immediate heartbeat (bypasses jitter) |
forge licenses [--html | --text] | Exports third-party dependency attribution |
Dependency License Audit
Section titled “Dependency License Audit”cargo-denypolicy covering all 6 release targetscargo-aboutgeneratesLICENSES.html(226 unique licenses across 552 crates)forge licensesembeds and exportsLICENSES.htmlLICENSES.htmluploaded to R2 alongside release binaries- Release manifest includes
licenses_urlfield
Air-Gapped Deployment Tier (Defense Wave)
Section titled “Air-Gapped Deployment Tier (Defense Wave)”- Cargo feature
air_gappedcompiles out heartbeat, update checks, and all network URLs at build time scripts/build-air-gapped.shbuilds customer-specific binaries with embedded license, seats, and expiration year- Air-gapped
forge updateprints renewal contact instructions instead of checking CDN - Air-gapped
forge config heartbeat showdisplays an air-gapped mode notice - Contact-sales model: $499/user/year, minimum 3 seats, annual only
Anti-Piracy Hardening (Defense Wave)
Section titled “Anti-Piracy Hardening (Defense Wave)”- Ed25519 public key obfuscated via 4 XOR’d shards — not visible in binary string analysis
- 8 scattered secondary license enforcement sites across hot paths: MCP dispatcher, workflow tools, search/graph tools, AST parser, CLI serve command
- Machine fingerprint computation: SHA-256 of hostname + MAC address + CPU brand + machine-id
- Machine fingerprint binding enforced per tier: Solo = 1 machine, Pro = 3 machines, Team = seats value
forge deactivatefully implemented (was a stub in v1.2.0)- Anti-debug detection on Linux (
TracerPid); macOS and Windows stubbed for v1.4.0 - Release profile hardened: fat LTO, codegen-units=1, strip=symbols, panic=abort
Changed
Section titled “Changed”- All
forgeengine.devreferences updated toforge.ironpinelabs.com forge statusshows trial badge when in trialforge licensedisplay restructured with tier-aware feature list (fixes v1.2.0 P1-1)- Release script (
scripts/release.sh) now bundlesLICENSES.html
- v1.2.0 P1-1:
forge activatesuccess message was hardcoded to Solo tier feature list. Now shows the actual features unlocked for the activated tier. forge deactivatemessage no longer incorrectly states “Pro feature only” — full implementation replaces the v1.2.0 stub.- Community Mode daily reset documented and enforced as UTC midnight (not local midnight).
Removed
Section titled “Removed”- Duplicate Hugo site at
sites/forgeengine.dev/— retired in favor of the canonical Astro site. 3 launch blog posts migrated toforge-site/src/content/blog/.
Security
Section titled “Security”- Heartbeat transmits only the SHA-256 hash of the license key — plaintext never leaves the machine
- Heartbeat endpoint rate-limited to 10 requests per license per day
- D1 migration 0002 is additive only (
ADD COLUMN, new tables) — no data loss risk - Dev private key sanitization verified across all docs — no regressions from v1.2.0
- Internal security posture documented at
docs/internal/forge-security-notes.md
Known Limitations
Section titled “Known Limitations”HEARTBEAT_URLplaceholder inforge-core/src/heartbeat.rsmust be updated to the production Cloudflare Worker subdomain before any release binary ships (hard launch blocker)- macOS and Windows anti-debug stubbed — target v1.4.0
- Integrity marker is a static constant, not a live machine-code hash — target v1.4.0
- Trial expiration grace window deferred to v1.3.1 (low-probability edge case during Stripe billing delays)
Upgrade Notes
Section titled “Upgrade Notes”No breaking changes from v1.2.0. Licenses signed by v1.2.0 still activate via #[serde(default)]
on new fields. Existing ~/.forge/license.json files load via the LocalLicenseRecord migration path.