Files
smart-org/docs/plan/reports/agent-1-phase-2.md
T

5.5 KiB

Agent 1 · Phase 2 — Org creation wizard + app profile (v2 A1-2)

Status: done. Backend + frontend + tests all green. Branch: dev (Gitea auto-deploys dev). Checks: ruff clean on new .py; test_org_wizard.py 16/16 pass; web tsc --noEmit clean; next lint clean; org-wizard.test.tsx 6/6 pass; org-sharing.test.tsx 5/5 pass.


Endpoints added (method + path + role)

Method Path Who
GET /api/setup/catalog any authenticated user
GET /api/setup/draft any authenticated user (row is user-scoped)
PUT /api/setup/draft any authenticated user (204, no secrets persisted)
POST /api/setup/check-git any authenticated user (URL format + SSRF check server-side)
POST /api/setup/check-deploy any authenticated user (TOFU fingerprint on success)
POST /api/setup/complete any authenticated user; 403 for role user, 409 if the caller already owns an app
GET /api/organizations/{org}/app/profile org member
PATCH /api/organizations/{org}/app/profile CAN_MANAGE_PROJECTS (owner/admin/manager)
PUT /api/organizations/{org}/app/deploy-target CAN_MANAGE_PROJECTS
PUT /api/organizations/{org}/app/git CAN_MANAGE_PROJECTS (credential rotation only — git source is fixed after creation)

Audit action organization.wizard_complete (ORG_WIZARD_COMPLETE) is written on complete.

Tables / migrations

  • New org_setup_drafts table via migration d5e6f7a8b9c0_org_setup_drafts.py (down_revision="a1b2c3d4e5f1", the Phase 1 head). Columns: id, user_id (FK users CASCADE), step, data_json, created_at, updated_at, index ix_org_setup_drafts_user_id.
  • App-profile columns on projects (app_type, language, framework, runtime_version, package_manager, setup/build/test/start_command, app_port, healthcheck_path, git_source, external_repo_url, wizard_completed_at) — added in the v2 foundation (TODO-0), not this phase.
  • UNIQUE(organization_id) on projects enforces 1 org = 1 app; the service returns a friendly 409 Persian message (این سازمان قبلاً یک اپلیکیشن دارد.) instead of a raw constraint error.

Files

Backend

  • app/domain/projects/catalog.py — pure-Python catalog (2.1): APP_TYPES, GIT_SOURCES, LANGUAGES → frameworks → ProfileDefaults; defaults_for(...).
  • app/infrastructure/db/models_org.py — OrgSetupDraftRow.
  • alembic/versions/d5e6f7a8b9c0_org_setup_drafts.py — migration.
  • app/application/services/org_setup_service.py — OrgSetupService (catalog, get_draft, save_draft, check_git, check_deploy, complete, get_profile, update_profile, update_deploy_target, update_git_credentials) + WizardPayload.
  • app/interfaces/http/routers/app_setup.py — all routes above (was a stub, pre-registered in rpc_app.py).
  • app/domain/audit/models.py — ORG_WIZARD_COMPLETE.
  • tests/test_org_wizard.py — 16 tests.

Frontend

  • packages/contracts/src/index.ts — CatalogPayload, CatalogLanguage/Framework/Defaults, WizardCompleteResult, AppProfile, DeployTargetSummary, and request bodies (SetupDraft, CheckGitBody, CheckDeployBody, WizardCompleteBody, DeployTargetPutBody, GitCredentialsPutBody, AppProfileUpdate).
  • apps/web/src/lib/api-org.ts — setupApi (wizard) + appProfileApi (org-scoped profile/deploy/git).
  • apps/web/src/app/onboarding/page.tsx — rebuilt as a 5-step wizard (stepper, back/next, draft auto-save + resume, secrets stripped from the draft).
  • apps/web/src/app/(app)/settings/page.tsx — new "اپلیکیشن" tab (AppTab): profile editing, git credential rotation, deploy-target edit + test.
  • apps/web/src/test/org-wizard.test.tsx — 6 tests (catalog load, slug auto-suggest, step navigation, secrets never in draft payload, manager-with-org redirect, plain-user waiting screen).

Contract consumption (frozen — unchanged)

  • RepoWorkspacePort.test_remote (Agent 3) — external git check.
  • DeployTargetTester.test_connection (Agent 3) — production deploy check.
  • WorkforceBootstrapPort.bootstrap_team (Agent 2) — called after commit.
  • DeliveryHooks.on_app_created (Agent 3) — called after commit; each hook called once, failure logged, never rolls back the org.

Manual QA steps

  1. As the owner, invite a manager (Phase 1 flow); log in as that manager → redirected to /onboarding.
  2. Step through: org name/slug → app type/language/framework (advanced accordion prefilled) → git (platform or own repo, "بررسی اتصال") → optional production deploy ("تست اتصال") → review → create.
  3. Success screen → "برو به مدیر AI" → /manager. GET /api/auth/me now returns needs_onboarding: false; exactly one projects row exists with a full profile.
  4. In the new org, open Settings → "اپلیکیشن": edit commands/port/healthcheck, rotate git credentials, set + test a deploy target. Secrets never appear in responses (only has_secret / masked values).
  5. Confirm a second POST /setup/complete returns 409.

Known limitations / open items

  • No GET for the deploy target exists yet (the service update_deploy_target only writes). The settings tab therefore shows post-save feedback from the PUT response (has_secret, last_test_ok, last_test_message) rather than a pre-filled form. A read endpoint can be added later without touching the contract.
  • Default model grants (Phase 3) are not copied on complete yet — complete passes deploy_target/git through; grant copy lands in Phase 3.3.
  • CHANGE REQUESTs: none blocking this phase.