Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1e408bf
refactor(billing): remove dead credit-granting code for org seat subs…
jeanduplessis Mar 23, 2026
2947edc
docs(billing): add reverse-engineered spec for team/enterprise seat b…
jeanduplessis Mar 26, 2026
3b78813
docs(billing): add monthly billing cycle and align spec structure
jeanduplessis Mar 26, 2026
7a1060f
docs: add spec template for future billing specs
jeanduplessis Mar 26, 2026
182143b
docs: add monthly billing UI prototype and implementation plan
jeanduplessis Mar 26, 2026
9bf38d3
feat(billing): add monthly billing cycle option for Team and Enterpri…
jeanduplessis Mar 26, 2026
1e61f3f
fix(billing): correct monthly billing regressions in resubscribe, cyc…
jeanduplessis Mar 28, 2026
791a443
fix(billing): address cycle-change correctness, discount preservation…
jeanduplessis Mar 28, 2026
ad90a19
fix(billing): detect pending cycle change from paid seat item, not it…
jeanduplessis Mar 28, 2026
06b51f6
fix(billing): derive plan tier from Stripe price, fix next-payment di…
jeanduplessis Mar 28, 2026
c1a11dd
fix(billing): exclude free-seat items from resubscribe and cycle-chan…
jeanduplessis Mar 28, 2026
bf805ab
feat(billing): enforce seat billing, add membership tombstones, KISS …
jeanduplessis Mar 29, 2026
2965c82
style: apply formatter fixes
jeanduplessis Mar 29, 2026
b1ab9fd
chore: remove planning and prototype files
jeanduplessis Mar 29, 2026
9e4110c
chore(db): squash branch migrations into single migration
jeanduplessis Mar 29, 2026
54164f8
fix(billing): enforce hard-expiry gate on auto-fix/triage mutations, …
jeanduplessis Mar 29, 2026
3fdf840
fix(billing): correct resubscribe defaults, billing cycle derivation,…
jeanduplessis Mar 29, 2026
733daec
fix(billing): clamp resubscribe seats to usage, allow expired orgs to…
jeanduplessis Mar 29, 2026
aea33e6
fix(billing): wait for seat usage before seeding resubscribe defaults
jeanduplessis Mar 29, 2026
5c9e8b2
fix(billing): prevent seatUsage refetches from resetting billing cycl…
jeanduplessis Mar 29, 2026
e739144
fix(billing): skip resubscribe seeding when user has already edited form
jeanduplessis Mar 29, 2026
fe2d4ae
fix(billing): fix subscription schedule metadata, support ended subs,…
jeanduplessis Mar 30, 2026
20ce4e6
chore(db): remove branch-local migration for rebase
jeanduplessis Mar 30, 2026
9f9025c
chore(db): regenerate migration after rebase on main
jeanduplessis Mar 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ WORKOS_API_KEY=invalid-mock-workos-key
WORKOS_CLIENT_ID=invalid-mock-workos-client-id
STRIPE_TEAMS_SUBSCRIPTION_PRODUCT_ID='STRIPE_TEAMS_SUBSCRIPTION_PRODUCT_ID'
STRIPE_ENTERPRISE_SUBSCRIPTION_PRODUCT_ID='STRIPE_ENTERPRISE_SUBSCRIPTION_PRODUCT_ID'
STRIPE_TEAMS_MONTHLY_PRICE_ID='price_test_teams_monthly'
STRIPE_TEAMS_ANNUAL_PRICE_ID='price_test_teams_annual'
STRIPE_ENTERPRISE_MONTHLY_PRICE_ID='price_test_enterprise_monthly'
STRIPE_ENTERPRISE_ANNUAL_PRICE_ID='price_test_enterprise_annual'
USER_DEPLOYMENTS_API_BASE_URL=''
USER_DEPLOYMENTS_API_AUTH_KEY=''
SESSION_INGEST_WORKER_URL=''
Expand Down
645 changes: 645 additions & 0 deletions .specs/team-enterprise-seat-billing.md

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions .specs/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# [Feature Name]

## Role of This Document

This spec defines the business rules and invariants for [feature].
It is the source of truth for _what_ the system must guarantee —
valid states, ownership boundaries, correctness properties, and
user-facing behavior. It deliberately does not prescribe _how_ to
implement those guarantees: handler names, column layouts,
conflict-resolution strategies, and other implementation choices
belong in plan documents and code, not here.

## Status

Draft -- created YYYY-MM-DD.

## Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in
BCP 14 [RFC 2119] [RFC 8174] when, and only when, they appear in all
capitals, as shown here.

## Definitions

- **Term**: Definition of a domain-specific term used throughout
this spec.

## Overview

A concise narrative (1-2 paragraphs) describing the feature from a
user and system perspective. Cover what the feature does, who it
serves, and the high-level lifecycle. Avoid implementation details.

## Rules

### [Section Name]

1. The system MUST ...
2. The system MUST NOT ...

## Error Handling

1. When [error condition], the system MUST [behavior].

## Not Yet Implemented

The following rules use SHOULD and reflect intended behavior that is
not yet enforced in the current codebase:

1. The system SHOULD ... (Currently ...)

## Changelog

### YYYY-MM-DD -- Initial spec

- Created from [source].
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Migrations live in `packages/db/src/migrations/` and are generated by `drizzle-k
- **After a rebase that conflicts on migration files:** delete all migration files, snapshots, and journal entries that were added on the branch, then re-run `pnpm drizzle generate` to regenerate a clean migration from the current schema diff. Re-append any backfill SQL afterward.
- Prefer a single migration per feature branch when the code has not yet been deployed to production. If multiple migrations accumulated during development, squash them by deleting all branch-local migrations and regenerating.

## Stripe Subscription Schedules

When using `subscriptionSchedules.create()` with `from_subscription`, Stripe prohibits setting `metadata` in the same call (it copies metadata from the subscription automatically). Set custom metadata (e.g., `origin` tags) in the subsequent `subscriptionSchedules.update()` call instead.

## KiloClaw Billing

Before making **any** changes related to KiloClaw billing — including bug fixes, new features, refactors, or reviews — you **must** first read the billing spec at `.specs/kiloclaw-billing.md`. This applies to all code paths that touch billing logic, pricing, invoicing, usage metering, or payment flows.
13 changes: 13 additions & 0 deletions packages/db/src/migrations/0065_low_mad_thinker.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CREATE TABLE "organization_membership_removals" (
"id" uuid PRIMARY KEY DEFAULT pg_catalog.gen_random_uuid() NOT NULL,
"organization_id" uuid NOT NULL,
"kilo_user_id" text NOT NULL,
"removed_at" timestamp with time zone DEFAULT now() NOT NULL,
"removed_by" text,
"previous_role" text NOT NULL,
CONSTRAINT "UQ_org_membership_removals_org_user" UNIQUE("organization_id","kilo_user_id")
);
--> statement-breakpoint
ALTER TABLE "organizations" ALTER COLUMN "require_seats" SET DEFAULT true;--> statement-breakpoint
CREATE INDEX "IDX_org_membership_removals_org_id" ON "organization_membership_removals" USING btree ("organization_id");--> statement-breakpoint
CREATE INDEX "IDX_org_membership_removals_user_id" ON "organization_membership_removals" USING btree ("kilo_user_id");
Loading
Loading