بنقرة واحدة
awcms-mini-tenant-provisioning
Kerjakan bagian mana pun dari modul tenant_provisioning AWCMS-Mini (Issue
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Kerjakan bagian mana pun dari modul tenant_provisioning AWCMS-Mini (Issue
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Kelola/konsumsi sistem Module Management AWCMS-Mini (registry, validasi komposisi registry base, tenant lifecycle enable/disable, settings, permission sync/status, navigation, job registry, health/readiness). Gunakan saat menambah field descriptor baru (permissions/navigation/settings/jobs/health) di modul lain, saat menambah modul domain baru langsung di `src/modules/` dan perlu memverifikasi registry base tetap valid (`bun run modules:compose:check`), saat menyelidiki kenapa suatu modul terlihat degraded/orphaned, atau saat mengubah perilaku enable/disable/settings/health module_management sendiri. Sesuai src/modules/module-management/README.md, epic
Pilih dan jalankan profil deployment AWCMS-Mini (development/staging/production/offline-LAN). Gunakan saat menyiapkan deployment baru, memutuskan LAN-first vs registry-based, atau deploy ke Coolify. Sesuai doc 18 dan deployment-profiles.md/deploy-coolify.md.
Kelola sistem log/audit/metrics AWCMS-Mini yang sudah aktif — correlation ID lintas hop, retensi/purge audit log, extension point untuk consumer eksternal (alerting/export/SIEM), dan metrics port (counter/histogram/gauge berkardinalitas rendah untuk request/pool/job/provider). Gunakan saat menambah endpoint baru (correlation ID otomatis), menjadwalkan purge audit log, memasang consumer log/audit di aplikasi turunan, atau menambah/mengonsumsi metrik operasional. Berbeda dari awcms-mini-audit-log (APA yang wajib diaudit) — skill ini tentang BAGAIMANA sistem log/audit/metrics itu sendiri dikelola, sesuai Issue
Triase dan perbaiki temuan CodeQL code scanning AWCMS-Mini (github.com/ahliweb/awcms-mini/security/code-scanning). Gunakan saat diminta "analisis code scanning"/"perbaiki CodeQL", saat sebuah PR gagal check CodeQL, atau saat menemukan alert baru. Mendokumentasikan satu TRUE-positive terkonfirmasi (password sungguhan → digest cepat yang dipersist = oracle cracking offline, plus dua "fix" yang membungkam alert tanpa memperbaiki apa pun) dan lima false-positive nyata (name-heuristic password, incompatible-types typeof/null, URL substring-sanitization di test mock, dua kasus dismiss resmi tanpa reformulasi kode, dan Bun.SQL tagged-template null-cast) plus pola "unused-local-variable di test kadang menandai coverage gap" — supaya tidak diinvestigasi ulang dari nol.
Daftarkan tabel bervolume tinggi ke registry lifecycle AWCMS-Mini (retensi/partisi/arsip/legal hold/purge), atau kerjakan bagian mana pun modul data_lifecycle sendiri. Gunakan saat menambah tabel baru yang tumbuh besar (log, telemetry, outbox, queue, provider attempt) dan butuh kebijakan retensi/purge aman, saat membuat/melepas legal hold, atau saat mengubah engine dry-run/archive/purge/archive-port. Sesuai Issue
Kerjakan satu issue/sprint AWCMS-Mini secara atomic dari awal sampai laporan. Gunakan saat diminta "implementasikan Issue X.Y", "kerjakan Sprint N", "buat fitur <modul>", atau saat memulai unit kerja AWCMS-Mini apa pun. Orkestrator yang memanggil skill AWCMS-Mini lain (migration, endpoint, event, idempotency, abac, audit) sesuai kebutuhan.
| name | awcms-mini-tenant-provisioning |
| description | Kerjakan bagian mana pun dari modul tenant_provisioning AWCMS-Mini (Issue |
tenant_provisioning (src/modules/tenant-provisioning, Issue #872, epic #868
SaaS control plane Wave 1, ADR-0022) adalah modul control-plane KETIGA —
Official Optional Business Foundation, opt-in per tenant, default-disabled,
tenant-scoped. Ia mengorkestrasi provisioning tenant idempoten/resumable
dari plan/step registry berversi, dengan durable checkpoint, lease/lock, bounded
retry, kompensasi diklasifikasi, dan reconciliation non-destruktif. PROVIDES
provisioning_status; CONSUMES fail-closed effective_entitlement (#871).
tenant_id (no soft
super-tenant). Operator kelola tenant target lewat konteks per-tenant
(SET LOCAL app.current_tenant_id), tiap command audited.awcms_mini_setup_state.tenant_id). Owner tenant yang ter-provision punya SEMUA
permission di tenant-nya sendiri — tanpa gate ini ia bisa baca run tenant lain.
Ditegakkan di src/pages/api/v1/tenant-provisioning/_support.ts authorizeOperator.createTenantOwner), TAK PERNAH disimpan; hanya fingerprint-nya
masuk inputs_hash. Step I/O minimal + redacted; tak ada token/secret di
payload/log/checkpoint.defaultTenantState:"disabled"; gated
tests/unit/module-governance-default-disabled.test.ts (key tenant_provisioning).tenant-provisioning/app|domain;
no-shared-table-write (awcms_mini_tenant_provisioning_* hanya ditulis modul ini);
cross-module via port (provisioning_status/provisioning_step) + injeksi di
composition root (_support.ts), BUKAN import langsung di app/domain.FOR UPDATE + state-predicate,
expired-lease reclaimable), UPDATE ter-predikat status → 409 bersih, idempotency
replay (request row = idempotency record: tenant_code unique + inputs_hash+key),
partial-column (transitionRequest CASE WHEN provided).checkpoint write-once
(NULL→non-null); request/step identity+plan+inputs frozen; status transitions
forward-legal only; no hard delete (REVOKE DELETE). Mirror pure di
domain/provisioning-state.ts.inputs_hash = idempotency binding (fingerprint password, bukan
plaintext), bukan data tenant-visible.application/request-parsing.ts:
absent→default; present→verbatim (validator tolak 400); nullable tri-state;
present-non-object owner/options→{}.Transaction model — durable checkpoint + provider di luar tx:
request: SATU tx — buat tenant (anti-dup tenant_code), owner, office, settings,
request+steps (bootstrap+owner PRE-COMPLETED, sisanya pending), emit requested.start/resume/retry: acquire lease → loop step, TIAP step tx SENDIRI (checkpoint
durable sebelum step berikut). waiting (provider) → event via outbox lalu pause.cancel: tolak bila lease hidup; kompensasi terklasifikasi; tenant tetap inactive.reconcile: desired-vs-actual, laporkan drift + safe action, TANPA auto-fix.State request: requested→in_progress→provisioned; in_progress→compensating→failed;
failed/blocked→in_progress (retry); provisioned→reconciling→provisioned; →canceled.
Readiness: pending/ready/blocked. Run gagal/cancel TAK PERNAH tinggalkan tenant
active — tenant inactive + status blocked/failed terlihat + readiness=blocked.
domain/compensation.ts: reversible→jalankan compensate handler (undo idempoten,
STATE saja); manual→manual_required; forbidden→skipped_forbidden (tenant
record + readiness). JANGAN hapus data tenant sebagai kompensasi generik.
tenant-admin/application/tenant-onboarding.ts
(dipakai BERSAMA setup wizard — satu implementasi). Refactor setup pakai helper
ini; jaga SQL/urutan identik.tenant_entitlement assign/cancel (#871) via
_support.ts buildEngineDeps().steps.entitlement.CoreStepDeps/registerProvisioningStep.domain/provisioning-plan.ts (plan berversi, registerProvisioningPlan) +
infrastructure/step-handler-registry.ts (registerProvisioningStep). Base:
standard_tenant v1 (tenant_bootstrap/owner_identity/default_configuration/
entitlement_assignment/module_preset/subdomain_request/readiness_check). Step tanpa
handler ter-resolve → FAIL CLOSED (blocked). Derived contribute tanpa edit engine.
application/control-plane-signals.ts — collectProvisioningSignals(tx, now),
dibaca bun run control-plane:fleet-sweep. Membaca HANYA tabel modul ini, di
dalam konteks RLS satu tenant; iterasi lintas-tenant ada di composition root
(ADR-0022 §6b — platform operator BUKAN soft super-tenant).
awcms_mini_tenant_provisioning_requests UNIQUE pada tenant_id —
provisioning 1:1 dengan tenant, jadi per tenant paling banyak SATU request.
Menguji beberapa status berarti menyiapkan beberapa TENANT, bukan beberapa
request.pending/running/waiting/failed) — sengaja, supaya label alert tidak
ikut tumbuh tiap kali status baru ditambahkan.failed masuk hitungan backlog tapi TIDAK menua. Ia tidak menunggu apa
pun; memasukkannya ke umur "oldest pending" membuat umur naik selamanya
setelah satu kegagalan dan mengunci alert terbuka.103).application/fleet-reconciliation.ts (kebijakan MURNI, nol akses DB) +
scripts/tenant-provisioning-fleet-reconcile.ts (composition root).
RECONCILE_MIN_INTERVAL_HOURS = 20, RECONCILE_MAX_TENANTS_PER_RUN = 200.
Jebakan yang sudah pernah menggigit: budget + urutan enumerasi = STARVATION.
Versi pertama menelusuri tenant sesuai urutan enumerasi lalu berhenti di batas
budget, dengan asumsi "filter kesegaran membuatnya berotasi". Itu SALAH: dengan
interval 20 jam pada cadence harian, setiap tenant yang disentuh pass sebelumnya
sudah basi lagi di pass berikutnya — jadi tenant yang sama terpilih selamanya dan
sisanya tidak pernah direkonsiliasi. Pola yang benar adalah dua fase: fase 1
probe SEMUA tenant (murah, baca lastReconciledAt saja), fase 2 urutkan menurut
kebasian (null dulu, lalu terlama) baru potong di budget. Kedua bentuk itu ada
di suite unit — termasuk test yang mereproduksi bentuk starvation-nya, jangan
dihapus karena "kelihatan redundan".
--dry-run tidak boleh memanggil mutasi sama sekali. Kegagalan per-tenant
dihitung lewat safeErrorDetail(error), bukan logScriptFailure (yang akan
berkelahi dengan applyJobExitCode).
application/owner-secret-commitment.ts. Body request provisioning memuat
password owner tenant baru, dan digest-nya disimpan di record idempotency —
SHA-256 polos di situ adalah verification oracle (pembaca kolom bisa
mengonfirmasi tebakan password).
Jangan "perbaiki" ke argon2id: nilai ini harus deterministik dan bisa
dihitung ulang dari body saat replay, sedangkan argon2id mengundi salt baru tiap
panggilan sehingga tidak pernah bisa dibandingkan sama. Jangan pula turunkan ke
HMAC polos: itu hanya memberi properti "keyed", tidak "costly", sehingga pepper
yang bocor langsung mengembalikan serangan instan. Parameter biaya dipin
eksplisit (digest dipersistensi lalu dibandingkan saat replay — default runtime
yang berubah akan membatalkan semua inputs_hash tersimpan secara diam-diam),
dan scrypt dibungkus tangan karena promisify runtuh ke overload tiga-argumen
dan diam-diam membuang parameter itu. Lihat
docs/awcms-mini/control-plane-security.md §5.
bun run check PENUH di DB PostgreSQL terisolasi FRESH (migration 085 diedit ⇒
migrate dari nol; jangan DB yang punya 083 lama = checksum drift). Test: state
transition/plan-validation/compensation-classification/error-handling (unit);
lease/idempotency/resume/RLS/event-same-commit (integration); failure-injection tiap
step boundary; concurrency duplicate-request + worker-restart; derived-step fixture;
E2E request→failure→resume→active; security secret/PII redaction + cross-tenant denial.
Blast radius: index.ts (26 modul), doc-reconciliation toBe(26) + heading "Peta 26",
doc 21 tabel+total, skill-coverage MAP, event-registry+AsyncAPI+OpenAPI, i18n.