mirror of
https://github.com/saltbo/zpan.git
synced 2026-08-28 15:51:29 +08:00
feat: add licenseBinding table, migration 0013_licensing, and shared licensing types (#339)
- Add `licenseBinding` singleton table (id=1) to server/db/schema.ts
- Correct `0012_image-hosting` journal idx from 11→12 (matches its prefix;
was left wrong by previous rename-only fix in ef1fab8), then auto-generate
migration 0013_licensing.sql via drizzle-kit
- New 0013_snapshot.json created; 0012_snapshot.json unchanged
- Add ProFeatures enum to shared/constants.ts
- Add shared/types/licensing.ts with LicenseEntitlement, ProFeature, BindingState
- Export new types from shared/types/index.ts
Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f
Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE `license_binding` (
|
||||
`id` integer PRIMARY KEY NOT NULL,
|
||||
`instance_id` text NOT NULL,
|
||||
`cloud_account_id` text,
|
||||
`cloud_account_email` text,
|
||||
`refresh_token` text NOT NULL,
|
||||
`cached_cert` text,
|
||||
`cached_expires_at` integer,
|
||||
`last_refresh_at` integer,
|
||||
`last_refresh_error` text,
|
||||
`bound_at` integer
|
||||
);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -80,11 +80,18 @@
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"idx": 12,
|
||||
"version": "6",
|
||||
"when": 1776749333797,
|
||||
"tag": "0012_image-hosting",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "6",
|
||||
"when": 1776997633827,
|
||||
"tag": "0013_licensing",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -136,6 +136,20 @@ export const shareRecipients = sqliteTable(
|
||||
],
|
||||
)
|
||||
|
||||
// licenseBinding — singleton (id=1 always); before binding no row exists
|
||||
export const licenseBinding = sqliteTable('license_binding', {
|
||||
id: integer('id').primaryKey(),
|
||||
instanceId: text('instance_id').notNull(),
|
||||
cloudAccountId: text('cloud_account_id'),
|
||||
cloudAccountEmail: text('cloud_account_email'),
|
||||
refreshToken: text('refresh_token').notNull(),
|
||||
cachedCert: text('cached_cert'),
|
||||
cachedExpiresAt: integer('cached_expires_at'),
|
||||
lastRefreshAt: integer('last_refresh_at'),
|
||||
lastRefreshError: text('last_refresh_error'),
|
||||
boundAt: integer('bound_at'),
|
||||
})
|
||||
|
||||
// image_hosting_configs — per-org singleton; row exists => feature enabled
|
||||
export const imageHostingConfigs = sqliteTable('image_hosting_configs', {
|
||||
orgId: text('org_id')
|
||||
|
||||
@@ -42,3 +42,12 @@ export const SignupMode = {
|
||||
} as const
|
||||
|
||||
export type SignupMode = (typeof SignupMode)[keyof typeof SignupMode]
|
||||
|
||||
export const ProFeatures = {
|
||||
WHITE_LABEL: 'white_label',
|
||||
OPEN_REGISTRATION: 'open_registration',
|
||||
TEAMS_UNLIMITED: 'teams_unlimited',
|
||||
TEAM_QUOTAS: 'team_quotas',
|
||||
} as const
|
||||
|
||||
export type ProFeatures = (typeof ProFeatures)[keyof typeof ProFeatures]
|
||||
|
||||
@@ -239,3 +239,5 @@ export interface ImageHosting {
|
||||
lastAccessedAt: string | null
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export type { BindingState, LicenseEntitlement, ProFeature } from './licensing'
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
export type ProFeature = 'white_label' | 'open_registration' | 'teams_unlimited' | 'team_quotas'
|
||||
|
||||
export interface LicenseEntitlement {
|
||||
account_id: string
|
||||
instance_id: string
|
||||
plan: 'community' | 'pro'
|
||||
features: ProFeature[]
|
||||
issued_at: number
|
||||
expires_at: number
|
||||
}
|
||||
|
||||
export interface BindingState {
|
||||
bound: boolean
|
||||
account_email?: string
|
||||
plan?: 'community' | 'pro'
|
||||
features?: ProFeature[]
|
||||
expires_at?: number
|
||||
last_refresh_at?: number
|
||||
last_refresh_error?: string
|
||||
}
|
||||
Reference in New Issue
Block a user