Skip to content

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 14:35
· 206 commits to main since this release
99560de

Added

  • intelligo admin grant <email>: makes a signed-up user a platform admin
    by writing users.role, and records an admin.platform_admin.granted
    audit event in the same transaction. With NODE_ENV=production it
    refuses unless --force is passed. PLATFORM_ADMIN_EMAILS counts only
    a verified address, which a development setup without an email provider
    never has.
  • A granted plan can end. grantPlan({ …, endsAt }) or { …, days }
    records the grant's period (days counts from the end of a running
    grant of the same plan, so renewals stack), and a local payment's plan
    grant takes days too: { plan: slug, days: 30 }. Without either, a
    grant has no end, as before, and clears an end an earlier grant left.
    GrantPlanResult carries endsAt. On a workspace Stripe bills, the
    plan moves and the period stays Stripe's.
  • processExpiredPlanGrants() in @intelligo-dev/billing returns every
    lapsed grant to the free plan, audited as billing.plan_grant.expired,
    and the maintenance template (1.2.0) runs it after trial expiry.
    A one-time QR payment therefore no longer grants its plan forever.
  • Local invoices settle without the buyer's tab. settlePendingLocalInvoices
    in @intelligo-dev/billing settles every unfulfilled invoice opened in
    the last day, or the one a provider's callback names, each against the
    workspace that recorded it and by asking the provider — a callback's
    body is never taken as payment. PaymentProvider gains an optional
    invoiceIdFromCallback(request); the mock reads ?invoice=. The
    payment-poll item ships app/api/payments/local/settle/route.ts
    (schedule it with CRON_SECRET, beside maintenance) and
    app/api/webhooks/local-payment/route.ts (the provider's callback URL),
    both granting through the new lib/local-payment-grant.ts, which the
    poll action now uses too.
  • withCronSecret(handler) in @intelligo-dev/next/route: 401 without
    Authorization: Bearer $CRON_SECRET, 403 to everyone while the secret
    is unset or shorter than 32 characters.
  • @intelligo-dev/core/storage/s3: a StorageAdapter for any
    S3-compatible bucket — AWS S3, Cloudflare R2, MinIO. createS3Storage
    takes the bucket, region, keys and an optional endpoint and
    pathStyle, and signs with Signature Version 4 over fetch and Web
    Crypto, so it adds no dependency; s3StorageFromEnv() builds
    one from STORAGE_BUCKET, STORAGE_ACCESS_KEY_ID,
    STORAGE_SECRET_ACCESS_KEY, STORAGE_REGION and STORAGE_ENDPOINT, or
    returns null without a bucket. The storage port's example no longer
    names an adapter that did not exist.

Changed

  • The scaffold's i18n/request.ts lays a locale's messages over the
    default locale's: a namespace or key a locale has not translated yet
    renders in the default language instead of throwing, so a locale can
    be translated a namespace at a time. intelligo sync --check still
    reports what is behind. app-scaffold 1.16.0.
  • intelligo migrate --check also checks the app's own chain: the
    migrations drizzle-kit generate wrote to ./drizzle against what
    drizzle-kit migrate recorded in drizzle.__app_migrations. A pending
    or unknown app migration exits 1, so the scaffold's db:check deploy
    gate no longer passes with the app's schema behind. --json carries it
    as app (null when the app owns no chain); state still describes
    the framework's chain and exitCode covers both.
  • Outside production, the console email provider logs the links a message
    carries (verificationUrl, resetUrl, …) beside its recipient and
    subject, so an address can be verified and a password reset without an
    email provider.

Fixed

  • @intelligo-dev/core's db maps a column declared without a name to
    snake_case, as the scaffold's drizzle.config.ts does: a consumer table
    written workspaceId: text() is queried as workspace_id, the column
    drizzle-kit generated. The framework's own columns are all named, so
    their SQL is unchanged.
  • The chat item's lib/chat-server-config.ts shows Mastra's
    handleChatStream with version: "v7", the stream AI SDK 7 reads.
  • The usage item's chart renders the same scale on server and client.
    UsagePage formats the axis labels in compact notation and passes them
    down (UsageChart takes max and scaleLabels), as the trial banner
    does: Node's and a browser's ICU spell compact numbers differently for
    many locales, which React reported as a hydration mismatch. An
    architecture test now refuses compact notation in any client component
    an item ships.
  • intelligo create inside a pnpm workspace no longer gives the app a
    package name another package has: create apps/app --name Acme in a
    workspace whose root is acme names the app @acme/app (the root's
    scope or name, then the directory). The page title and billing product
    still come from --name. The package name is its own template variable,
    __PACKAGE_NAME__ (app-scaffold 1.17.0); an app recorded before it
    reads as named __APP_NAME__, so its package.json stays current.
  • intelligo doctor warns when the app's package name is also another
    workspace package's — pnpm --filter and workspace:* resolve only one.