Tech Connector Licensing Architecture
Tech Connector uses a local-first entitlement client shared by the desktop app, headless API, and supported DCC/game-engine hosts. The licensing service receives identity, entitlement, project-registration, and activation metadata only. It does not receive project assets, scene data, animation, source files, local paths, prompts, or other creative content.
Domain and trust boundaries
The public client contains domain models, policy evaluation, replaceable ports, a stable project UUID manifest, and an Ed25519 public-key verifier. It does not contain token-signing functions, private signing keys, payment credentials, or backend administration code.
Production private keys, account records, organization membership, canonical license terms, payments, accounting, and entitlement issuance belong to a separate private backend.
Source and product distribution use a public-monorepo/private-services boundary. Tech Connector Core and the complete first-party Official Tools source are publicly source-available together. Official Tools execution and official release/update delivery remain capability-controlled. Backend services, signing, billing, accounting, administration, and enterprise-only components remain private. GitHub App and OAuth secrets never enter the client or signed entitlement. See SOURCE_ACCESS_MODEL.md.
Authentication sessions are short-lived and separate from signed offline
entitlements. Refresh credentials must be stored through an operating-system
credential-store adapter. A signed entitlement may be cached locally and used
until its offline expiration. refresh_after produces a warning; expires_at
requires online revalidation.
An issuer may deliver the same signed entitlement as a .tclicense file for
offline installation. The file contains one compact TC-ENT Ed25519 token,
not editable JSON or a client-generated key. The activation and License &
Activation dialogs import it through the existing signature, issuer, audience,
active-license, verified-email, device-binding, and expiry checks before it is
cached. Project and product policy is still evaluated at use time. Files over
64 KiB or containing more than one token are rejected. A copied file for a
different installation cannot activate this device; the private issuer must
issue a new device-bound entitlement.
The website's license sign-up dialog currently sends an access request through
the site's contact form provider. It does not create an account, process a
payment, issue a .tclicense file, or grant an entitlement. The desktop
activation dialog is a fallback when no valid active entitlement is present:
it links to that website form, shows a copyable pseudonymous installation ID
for manual issuance, and imports a signed file. A valid active entitlement
denied for project or version policy shows the policy denial instead of
reopening the sign-up dialog. The configured account endpoints still require
a live issuer service before browser sign-in can complete.
Client modules
tech_connector/licensing/domain.py: versioned domain values.tech_connector/licensing/verification.py: strict Ed25519 verification.tech_connector/licensing/policy.py: offline, project, version, and device policy.tech_connector/licensing/project_identity.py: privacy-safe project UUIDs.tech_connector/licensing/local_storage.py: separate signed-token cache and random installation identity without hardware fingerprinting, plus a privacy-safe local licensing audit sink.tech_connector/licensing/acceptance.py: a readable local acceptance-receipt file containing the local notice acknowledgement and evidence extracted from a verified signed entitlement, never the raw token or account email.tech_connector/licensing/context.py: runtime signature and project/device policy composition.tech_connector/licensing/ports.py: replaceable auth, network, storage, clock, device, and audit boundaries.tech_connector/config/licensing.json: public endpoints, public keys, issuer, audience, and non-economic safety limits.
ApplicationService owns the default licensing context. The headless API now
evaluates production-format signed entitlements through that same contract,
including the current project UUID, installation identity, application major
version, offline window, and commercial-use declaration. The desktop activation
UI uses the provider-neutral HTTPS contract in
LICENSING_BACKEND_API.md; the private service
implementation remains external.
Startup gate and acceptance receipts
Desktop startup verifies the signed entitlement before constructing MainWindow.
Only a verified Community entitlement shows the local Community license notice;
Indie, Enterprise, and Custom entitlements use their recorded verified-account
agreement and do not show that Community prompt. A Community notice must be
acknowledged before its entitlement authorizes host bridges. This prevents indexers, watchers,
model services, game-engine runtime services, and DCC bridges from starting
without an allowed entitlement. The receipt is written before an entitlement
can authorize host bridges; a receipt-storage failure therefore fails closed.
The readable local copy is stored at
<application-data>/licensing/license_acceptance_receipts.json. License
Management displays that exact path and provides Open Acceptance Receipts.
It contains agreement version and time plus opaque account, organization,
license, offer, and token IDs needed to identify the verified grant. It does
not contain the raw entitlement, email address, password, refresh credential,
project path, asset name, scene content, or other creative data. This file is
informational and user-visible; the immutable private-backend record and signed
entitlement are the authoritative evidence.
Embedded Maya, Blender, Unreal, Houdini, MotionBuilder, Substance Painter,
Unity, 3ds Max, and GIMP runtimes use a short-lived local bridge capability
because host runtimes cannot be assumed to support the production cryptography
package. The standalone or signed headless client issues this random capability
only after the shared entitlement policy succeeds and the entitlement includes
dcc_host_access. It expires after at most 12 hours and never outlives the
signed offline entitlement. DCC execution servers reject a missing, expired,
wrong-host, or incorrect capability before dispatching the official request.
Maya uses a dedicated JSON socket rather than its raw Python commandPort, so
authorization occurs before code decoding and main-thread execution.
The bridge-session file contains only its schema, random token, issue/expiration times, and allowed host IDs. It contains no account, organization, license, project, asset, scene, prompt, or financial metadata. It is a local process authorization mechanism, not a replacement license or backend entitlement.
Auxiliary localhost APIs are part of the same trust boundary. In particular, the Unreal Project Intelligence daemon requires the Unreal bridge capability before exposing status, project paths, context, scans, capability execution, or shutdown. A host integration that cannot validate an entitlement-derived local capability must remain disabled in production until a compatible pairing design exists.
The checked-in configuration contains a render-preview key and endpoint addresses, not proof of a live production issuer. A signed token is cached only after its signature, verified-email state, active-license state, offline window, and installation binding pass validation.
Production release validation checks every required endpoint as a credential-free HTTPS URL, rejects query strings and redirects, validates each Ed25519 public key, and constrains the offline window to no more than 90 days. Signed claims must also agree across account subject, individual/organization grantee, project IDs, activation counts, and entitlement dates.
Grant model and customer segment
Entitlement schema v2 separates two concepts that must not be conflated:
license.typeis the economic/legal grant model:community,perpetual, orcustom.license.market_segmentis the signed customer classification:community,indie,enterprise, orcustom.
The signed offer_id identifies the backend-configured offer, while
classification_version records the version of the studio-size classification
rules used when the entitlement was issued. Prices, residual rates, thresholds,
seat counts, support, update windows, and capabilities remain explicit signed
claims or referenced versioned terms; the client never derives them from the
market segment.
Optional products use signed capability identifiers rather than inferred tier
names. Core startup remains controlled by the ordinary signed entitlement. The
single complete first-party tools product uses official_tools_bundle.
Community, Indie, Enterprise, and Custom offers may include or omit that
capability without creating individual Maya, Blender, rigging, or engine tool
SKUs. Independently configured user project/tool directories are not treated as
the Official Tools Bundle merely because Core can discover them.
| Market segment | Supported grant models | Required boundary |
|---|---|---|
| Community | Community | Commercial projects use registered, versioned project terms. |
| Indie | Community, perpetual, or custom | Named-user seat, signed studio-size band, and classification version are required. |
| Enterprise | Perpetual or custom | Named-user seat, organization grantee, and explicit enterprise_use capability are required. |
| Custom | Perpetual or custom | The signed offer, terms, limits, and capabilities control. |
Schema-v1 tokens remain valid during migration. They map Community grants to the Community segment and other legacy grants to Custom. New production issuance should use schema v2; a refresh can upgrade an existing v1 entitlement without changing its accepted agreement or project terms.
For Indie and Enterprise, limits.seat_count is the purchased organization
pool and the token's seat_assignment binds one seat to the authenticated
principal.account_id. Its status must be active. activation.active_device_count
is that named user's device count and is checked against
device_limit_per_seat, not against the entire organization pool. Organization
administrators may reassign seats through the private account portal, but a
seat is never a shared concurrent-user identity. Non-human build, render, or
service automation requires a separately modeled Custom/Enterprise capability.
Community project economics
Community commercial use requires project registration. No residual is owed on the first USD $500,000 of Adjusted Project Profit for a registered project. The signed project terms specify the measurement period and the rate applicable only above that threshold. Rates, prices, and studio-size schedules are backend data, not client constants.
New project terms may use marginal_brackets. Each signed bracket contains an
inclusive lower profit boundary, an exclusive upper boundary (or no upper bound
for the final bracket), and a rate in basis points. Brackets must begin at the
no-residual threshold, remain contiguous, cover all higher profit, and never
decrease in rate. A higher bracket applies only to profit inside that bracket;
it does not retroactively reprice lower profit. Legacy terms using one
flat_above_threshold rate remain valid.
licensing/economics.py provides an integer, half-up-rounded local estimate for
display and testability. It consumes only already signed terms and reported
Adjusted Project Profit. It does not collect financial data or replace the
private backend's authoritative statements, adjustments, invoices, or dispute
workflow.
The Community measurement period is the registered project's lifetime. Signed terms also identify the receipts basis, eligible-cost standard, related-party arm's-length standard, owner-labor standard, shared-cost allocation standard, and excluded cost categories. The client displays these terms but does not perform authoritative financial accounting.
Offline behavior
A perpetual license grants continuing rights to the covered major version, but the cached proof of that right still expires and must periodically be refreshed. Device binding is deliberately soft: a user can deactivate an old device and activate a replacement. The signed entitlement carries only a pseudonymous device hash and activation metadata. The default device adapter generates a random per-installation UUID; it does not read a MAC address, hostname, disk serial number, CPU identifier, or other hardware fingerprint.
When offline proof expires, the application should preserve access to local data and provide a clear reactivation path. Destructive changes, deletion, or upload of user work are never license-remediation actions.
Legacy migration
services/license_entitlement_service.py retains legacy tc1 HMAC helpers only
for explicit source-level compatibility tests. Legacy grants are disabled by
default and cannot be enabled in a frozen release. Production clients accept
only asymmetric signed entitlements selected by public key ID.
Release staging rejects private-key PEM markers and common production-secret artifacts before constructing a distributable package.