Skip to content

Commit fc88120

Browse files
authored
refactor(kiloclaw): removed managed Composio onboarding (#3543)
* refactor(kiloclaw): retire managed Composio onboarding * fix(kiloclaw): preserve manual Composio provenance until cleanup * fix(kiloclaw): keep new Composio settings unmanaged
1 parent 6802d01 commit fc88120

20 files changed

Lines changed: 200 additions & 2541 deletions

.specs/kiloclaw-composio.md

Lines changed: 57 additions & 227 deletions
Large diffs are not rendered by default.

.specs/kiloclaw-datamodel.md

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ background jobs). All consumers MUST comply with the rules below.
2121

2222
Draft -- created 2026-04-15.
2323
Updated 2026-05-12 -- required KiloClaw price-version lineage invariants.
24+
Updated 2026-05-27 -- required durable fresh-provision admission reservations.
2425
Updated 2026-05-28 -- fraud-enforcement subscription mutation invariants.
2526

2627
## Conventions
@@ -68,6 +69,11 @@ capitals, as shown here.
6869
Fraud Warning under `.specs/stripe-early-fraud-warnings.md`.
6970
- **Active instance**: An instance record that has not been marked
7071
as destroyed.
72+
- **Provision reservation**: Durable coordination state for one fresh
73+
provisioning attempt in a user context. A reservation assigns the
74+
candidate instance identifier that the attempt MUST use if it succeeds,
75+
but it is not an instance record, does not assert that infrastructure
76+
exists, and does not grant access.
7177
- **Mutation**: Any database write (INSERT or UPDATE) to a
7278
`kiloclaw_subscription` row that changes one or more of its
7379
business-relevant fields (status, plan, billing period, payment
@@ -187,6 +193,40 @@ KiloClaw billing.
187193
9. When the single-instance limit is relaxed in the future, no
188194
schema migration SHALL be required.
189195

196+
### Fresh Provision Admission
197+
198+
1. Before a fresh personal or organization-context provision invokes an
199+
instance Durable Object or any infra provider operation, the KiloClaw
200+
Worker MUST persist a provision reservation for the requesting user and
201+
context.
202+
2. A provision reservation MUST remain coordination metadata only. It MUST
203+
NOT be stored as an instance record, routed as an active instance, treated
204+
as billing access, or reported as completed onboarding.
205+
3. A provision reservation MUST assign one candidate instance identifier.
206+
An admitted attempt MUST carry that identifier through Durable Object
207+
routing, instance record insertion, subscription bootstrap, and routing
208+
registry publication; runtime MUST NOT silently choose a replacement
209+
identifier during that attempt.
210+
4. While an admitted fresh attempt is in progress or its provider-side
211+
outcome requires reconciliation, another fresh attempt for the same user
212+
and context MUST NOT execute provider creation work. The system MUST fail
213+
closed or report a retryable conflict rather than risk duplicate
214+
infrastructure.
215+
5. Before performing provider creation under an admitted reservation, the
216+
Worker MUST reconcile authoritative active-instance state for the same
217+
user/context. Existing active state MUST prevent another fresh provision
218+
even if a routing index entry is absent or stale.
219+
6. If a provision attempt fails after provider resources may have been
220+
created, its reservation MUST remain blocked or marked for reconciliation
221+
until cleanup or canonical recovery has been confirmed. An expired request
222+
or lease alone MUST NOT authorize another fresh attempt.
223+
7. A completed instance that is intentionally destroyed MAY later be
224+
reprovisioned when no active instance remains in the context, subject to
225+
subscription successor-transfer and entitlement rules.
226+
8. Reservation storage and admission enforcement MUST remain application/
227+
Worker-layer behavior; they MUST NOT introduce a schema-level constraint
228+
that prevents future multi-instance product behavior.
229+
190230
### Operational Instance Markers
191231

192232
Instance records MAY store operational lifecycle markers that do not
@@ -287,10 +327,12 @@ MUST be enforced only after the existing data model has been brought
287327
into the desired state (rules 1–6 satisfied, early-bird backfill
288328
complete).
289329

290-
19. A Cloudflare Worker Durable Object and a infra provider base resource MUST both exist
330+
19. A Cloudflare Worker Durable Object and an infra provider base resource MUST both exist
291331
before an instance record is created in `kiloclaw_instance`.
292332
Infrastructure MUST be provisioned first; the record is a
293-
reflection of existing infrastructure, not a reservation.
333+
reflection of existing infrastructure, not a reservation. A
334+
provision reservation created under Fresh Provision Admission is
335+
coordination metadata and does not violate this creation order.
294336
20. If either infrastructure component fails to provision, the system
295337
MUST NOT create an instance record. Cleanup of any partially
296338
provisioned infrastructure is the responsibility of the
@@ -350,6 +392,11 @@ not yet enforced in the current codebase:
350392
across all services that mutate subscription records. Some
351393
subscription-creation paths may already write change-log entries;
352394
complete cross-service coverage remains the intended invariant.
395+
4. Fresh Provision Admission SHOULD be implemented in the Registry-backed
396+
Worker admission flow before the existing web advisory lock is removed.
397+
(Currently, web requests use transitional PostgreSQL advisory-lock
398+
coordination that is being replaced because it is unsafe through
399+
transaction-pooled production connections.)
353400

354401
## Changelog
355402

@@ -358,6 +405,12 @@ not yet enforced in the current codebase:
358405
- Defined enforced personal Stripe Early Fraud Warnings as exceptional immediate cancellation/suspension mutations that retain instance history, write system-attributed change logs, and preserve the seven-day destruction grace.
359406
- Excluded organization-owned warnings from automatic organization-managed instance or subscription mutation.
360407

408+
### 2026-05-27 -- Required durable fresh-provision admission reservations
409+
410+
- Defined provision reservations as non-routable, non-entitling coordination state.
411+
- Required Worker-side admission before any fresh provider creation and fail-closed handling for concurrent or ambiguous failed attempts.
412+
- Preserved Worker-only instance insertion and infrastructure-before-row ordering.
413+
361414
### 2026-05-12 -- Required KiloClaw price-version lineage invariants
362415

363416
- Added required `kiloclaw_price_version` row semantics.

apps/web/src/app/(app)/claw/components/ClawOnboardingFakeWalkthrough.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import { ProvisioningStepView } from './ProvisioningStep';
2323

2424
const FAKE_STEP_LABELS: Record<ClawOnboardingRenderStep, string> = {
2525
identity: 'Identity',
26-
tools: 'Tools',
2726
calendar: 'Calendar',
2827
email: 'Inbound Email',
2928
interests: 'Interests',
@@ -172,13 +171,12 @@ type RenderFakeStepInput = {
172171
};
173172

174173
function getFakeStepProgress(step: ClawOnboardingRenderStep): StepProgress {
175-
return getClawOnboardingStepProgress(getFakeOnboardingStep(step), true, true, false);
174+
return getClawOnboardingStepProgress(getFakeOnboardingStep(step), true, true);
176175
}
177176

178177
function getFakeOnboardingStep(step: ClawOnboardingRenderStep): OnboardingStep {
179178
switch (step) {
180179
case 'identity':
181-
case 'tools':
182180
case 'calendar':
183181
case 'email':
184182
case 'interests':
@@ -195,7 +193,6 @@ function renderFakeStep({ step, setStep, stepProgress, basePath }: RenderFakeSte
195193
case 'identity': {
196194
return <BotIdentityStep {...stepProgress} onContinue={() => setStep('calendar')} />;
197195
}
198-
case 'tools':
199196
case 'calendar': {
200197
return (
201198
<CalendarConnectStepView

apps/web/src/app/(app)/claw/components/ClawOnboardingFlow.state.test.ts

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,6 @@ describe('ClawOnboardingFlow state machine', () => {
101101
expect(state.instanceStatus).toBeNull();
102102
});
103103

104-
test('allows managed tools before initial provisioning starts', () => {
105-
const state = getClawOnboardingFlowState(
106-
createInput({
107-
onboardingStep: 'tools',
108-
hasBotIdentity: true,
109-
hasToolsStep: true,
110-
})
111-
);
112-
113-
expect(state.renderStep).toBe('tools');
114-
expect(state.createSetupActive).toBe(false);
115-
expect(state.instanceStatus).toBeNull();
116-
});
117-
118104
test('keeps create setup active once an instance status exists', () => {
119105
const state = getClawOnboardingFlowState(
120106
createInput({
@@ -130,16 +116,6 @@ describe('ClawOnboardingFlow state machine', () => {
130116
expect(getClawOnboardingFlowState(createInput({ createSetupStarted: true })).renderStep).toBe(
131117
'identity'
132118
);
133-
expect(
134-
getClawOnboardingFlowState(
135-
createInput({
136-
createSetupStarted: true,
137-
onboardingStep: 'tools',
138-
hasBotIdentity: true,
139-
hasToolsStep: true,
140-
})
141-
).renderStep
142-
).toBe('tools');
143119
expect(
144120
getClawOnboardingFlowState(
145121
createInput({
@@ -210,28 +186,6 @@ describe('ClawOnboardingFlow state machine', () => {
210186
expect(getClawOnboardingStepProgress('done')).toEqual({ currentStep: 5, totalSteps: 5 });
211187
});
212188

213-
test('managed tools step replaces calendar in the active wizard', () => {
214-
const state = getClawOnboardingFlowState(
215-
createInput({
216-
createSetupStarted: true,
217-
onboardingStep: 'calendar',
218-
hasBotIdentity: true,
219-
hasToolsStep: true,
220-
})
221-
);
222-
223-
expect(state.renderStep).toBe('tools');
224-
expect(state.totalSteps).toBe(5);
225-
expect(getClawOnboardingStepProgress('tools', true, true, true)).toEqual({
226-
currentStep: 2,
227-
totalSteps: 5,
228-
});
229-
expect(getClawOnboardingStepProgress('calendar', true, true, true)).toEqual({
230-
currentStep: 2,
231-
totalSteps: 5,
232-
});
233-
});
234-
235189
test.each(CLAW_ONBOARDING_PROVISIONING_STATUSES)(
236190
'renders the post-provisioning spinner while machine status is %s',
237191
status => {
@@ -443,21 +397,6 @@ describe('ClawOnboardingFlow state machine', () => {
443397
expect(state.renderStep).toBe('calendar');
444398
});
445399

446-
test('renders tools in post-provisioning mode when explicit Composio resume is requested', () => {
447-
const state = getClawOnboardingFlowState(
448-
createInput({
449-
mode: 'post-provisioning',
450-
status: createStatus('running'),
451-
onboardingStep: 'tools',
452-
hasBotIdentity: true,
453-
hasToolsStep: true,
454-
gatewayState: 'running',
455-
})
456-
);
457-
458-
expect(state.renderStep).toBe('tools');
459-
});
460-
461400
test('renders calendar in post-provisioning mode even before the gateway is ready', () => {
462401
// The OAuth round-trip can complete before the gateway boots; respect
463402
// the calendar resume regardless of postProvisioningReady.

0 commit comments

Comments
 (0)