refactor(backend): collapse entitlement provider abstraction back to LicenseService (#889)

Removes backend/src/entitlements/ (registry, loadProvider,
CommunityEntitlementProvider, types, headers, normalize) and the two
abstraction-only tests. Relocates headers/normalize/types to
services/license-*.ts. Swaps 22 consumer call sites from
getEntitlementProvider() to LicenseService.getInstance(). Drops the
Dockerfile install step plus PRO_PACKAGE_VERSION build-arg and
github_token BuildKit secret in docker-publish.yml. Removes the now
stale no-restricted-imports rule in backend/eslint.config.mjs.

Net: 37 files changed, ~700 lines removed, no behavior change. Local
dev no longer requires GitHub Packages auth to start the backend.

Rationale and revisit conditions in
docs/internal/adrs/2026-05-02-collapse-entitlement-provider.md.
This commit is contained in:
Anso
2026-05-02 23:45:44 -04:00
committed by GitHub
parent 6929dad540
commit e5b1c7b22b
39 changed files with 150 additions and 735 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
import type { UserRole, ApiTokenScope } from '../services/DatabaseService';
import type { LicenseTier, LicenseVariant } from '../entitlements/types';
import type { LicenseTier, LicenseVariant } from '../services/license-types';
// Extend Express Request type for user and node context.
// This file is imported for its side effects only (ambient declaration).
-34
View File
@@ -1,34 +0,0 @@
/**
* Ambient declaration for the private `@studio-saelix/sencho-pro`
* package so the public Sencho core's TypeScript build passes whether
* or not the package is installed locally. The runtime shape is
* defined by the package itself; this stub mirrors the surface the
* loader uses and nothing more.
*
* In production CI the Dockerfile installs the real package; the stub
* is shadowed by the package's own types and any drift fails the
* build. Local development without GitHub Packages auth falls back to
* the stub plus the loader's in-tree LicenseService binding, which
* keeps `npm install` and `tsc` working for everyone.
*
* The `implements EntitlementProvider` clause carries the full method
* surface; we do not redeclare individual methods here. If the real
* package ever ships a narrower return type than the interface
* permits, the local stub would over-widen and lose call-site type
* info — but call sites only consume the interface (via the registry),
* so that risk does not materialise.
*/
declare module '@studio-saelix/sencho-pro' {
import type { EntitlementProvider } from '../entitlements/types';
/** Minimal database surface the provider needs. The public core's
* `DatabaseService` satisfies this structurally. */
export interface DatabaseAdapter {
getSystemState(key: string): string | null;
setSystemState(key: string, value: string): void;
}
export class LemonSqueezyEntitlementProvider implements EntitlementProvider {
constructor(db: DatabaseAdapter);
}
}