AlurKerja Python SDK untuk Script Addon
Memanggil service AlurKerja (mis. master data) dari script addon tanpa konfigurasi manual
Script addon Python bisa memanggil service AlurKerja — misalnya membaca atau menambah master data — tanpa menyimpan token, URL, atau ID tenant di konfigurasi addon. Platform mengisi kredensialnya otomatis lewat ctx.svc, dan AlurKerja Python SDK membungkus pemanggilan HTTP-nya.
Halaman ini melanjutkan Pembuatan Addon pada AlurKerja: struktur addon, index.json, dan kontrak run(ctx) di sana tetap berlaku.
1. Cara Kerja
Service Task BPMN (addon action)
│
▼
Camunda ── POST /api/v1/integration/addons/{addon}/execute/{action}
│ body: variables, parameters, configuration, process
▼
integration-service
1. Addon opt-in svc? (index.json → "svc": {"enabled": true})
2. Pemanggil = Camunda? (service account INTEGRATION_AUTH_CLIENT_ID)
3. Versi BPMN yang berjalan (camunda.act_re_procdef)
4. Siapa yang men-deploy versi itu (camunda.act_hi_op_log)
5. Deployer masih admin SOP / owner di workspace?
6. Buat token atas nama deployer (impersonation Keycloak)
│
▼
python3 scripts/<action>/<action>.py --run <ctx.json>
ctx.svc = { token, baseurl, tenant, process, actor }
│
▼
AlurkerjaSDK.from_ctx(ctx).get("probis", "masterdata", ...)Hal yang perlu diingat:
- Token milik user yang men-deploy versi BPMN yang sedang dijalankan proses tersebut, bukan user yang sedang login. Script mendapat hak akses sebesar hak akses deployer itu.
- Deployer wajib masih berperan admin SOP atau owner di workspace. Kalau tidak, eksekusi ditolak sebelum script dijalankan (lihat Bagian 9).
ctx.svchanya ada untuk actionSCRIPTyang dipanggil dari Service Task BPMN. Jalur API addon (/{tenant_setting_id}/api/{action}) tidak menerimanya.ctx.svctidak disimpan di riwayat eksekusi addon.- Bentuk balasan script juga diurus SDK — lihat Bagian 8.4.
2. Prasyarat
| Kebutuhan | Keterangan |
|---|---|
| Python | python3 ≥ 3.8 di host/container integration-service (script dijalankan dengan python3) |
| SDK | alurkerja-sdk terpasang untuk python3 tersebut (Bagian 3) |
| Deployer BPMN | Men-deploy BPMN dengan role admin SOP atau owner |
| integration-service | Env INTEGRATION_AUTH_CLIENT_ID sama dengan client Camunda, dan PROXY_SERVICE_URL terisi |
3. Instalasi SDK
Di host atau image integration-service:
python3 -m pip install --upgrade pip
python3 -m pip install "git+https://github.com/alurkerja-id/alurkerja-addon-python-sdk.git@v0.3.0"
python3 -c "import alurkerja_sdk; print(alurkerja_sdk.__version__)"Di repository addon, catat dependensinya di requirements.txt:
alurkerja-sdk @ git+https://github.com/alurkerja-id/alurkerja-addon-python-sdk.git@v0.3.0Untuk pengembangan lokal cukup pip install -r requirements.txt.
4. Opt-in di index.json
Tambahkan blok svc di level atas index.json:
{
"name": "mockapi",
"version": "1.0.0",
"type": "REST",
"svc": {
"enabled": true
}
}Nilai ini disimpan saat addon di-install atau di-publish. Addon yang sudah terpasang sebelum opt-in ditambahkan harus di-publish ulang; tanpa itu ctx.svc tidak pernah dikirim.
5. Isi ctx yang Diterima Script
{
"variables": {
"master_data_slug": "customers",
"harga": 75000
},
"parameters": {
"page": 0,
"page_size": 10
},
"configuration": {},
"runkey": "exec-1789123456789-getMasterDataRecords",
"svc": {
"token": "eyJhbGciOi...",
"baseurl": "https://onprem.merapi.alurkerja.com",
"tenant": {
"id": 1,
"name": "Tenant A",
"slug": "tenant-a",
"uuid": "f8672713-7ec0-4a8a-98ba-f6adf420d105"
},
"process": {
"definitionId": "pengajuan-cuti:7:3f1c",
"key": "pengajuan-cuti",
"name": "Pengajuan Cuti",
"version": 7,
"deploymentId": "a41b",
"tenantId": "c3a9…",
"instanceId": "9c2e",
"businessKey": "CUTI-2026-001",
"activityId": "Activity_ambil_md",
"activityName": "Ambil Master Data"
},
"actor": {
"email": "deployer@example.com",
"source": "deployer"
}
}
}Field svc | Keterangan | Di SDK |
|---|---|---|
token | Access token Keycloak milik deployer, berumur pendek | dipakai otomatis sebagai Authorization: Bearer |
baseurl | Gateway AlurKerja | sdk.api_url (selalu diakhiri /api/v1) |
tenant | Workspace tempat proses berjalan | sdk.tenant.id, .name, .slug, .uuid — slug otomatis dikirim sebagai header x-active-tenant |
process | BPMN yang sedang berjalan | sdk.process.key, .version, .activity_id, .instance_id, … |
actor | Pemilik token | sdk.actor.email, sdk.actor.source |
6. Contoh: Membaca Record Master Data
Struktur file di addon:
mockapi/
├── index.json
├── requirements.txt
└── scripts/
└── get_masterdata_records/
├── get_masterdata_records.py
└── request.example.json6.1 Script
scripts/get_masterdata_records/get_masterdata_records.py:
#!/usr/bin/env python3
"""
Get Master Data Records Script
Membaca record master data tenant aktif lewat AlurKerja SDK.
Mengikuti General Action Executor contract.
Butuh paket `alurkerja-sdk` dan `ctx.svc` (token, baseurl, tenant), yang diisi
platform otomatis karena addon ini opt-in `svc.enabled` di index.json.
"""
import sys
import json
import argparse
try:
from alurkerja_sdk import (
AlurkerjaSDK,
AlurkerjaAPIError,
AlurkerjaConfigError,
AlurkerjaRequestError,
exit_code_for,
)
except ImportError:
AlurkerjaSDK = None
def run(ctx):
"""
Entry point untuk action script (wajib bernama 'run')
Args:
ctx: Execution context dengan struktur:
- variables: Data runtime (dapat dimodifikasi), termasuk
`master_data_slug` (wajib) dan `harga` (opsional, untuk business
rule batas harga)
- parameters: page, page_size, search, order, orderBy
- configuration: Konfigurasi addon/plugin
- svc: {token, baseurl, tenant, process, actor} dari platform
- runkey: Unique identifier untuk tracing
Returns:
dict: Response dengan format standard
"""
parameters = ctx.get("parameters", {})
variables = ctx.get("variables", {})
slug = variables.get("master_data_slug")
harga = variables.get("harga")
sdk = AlurkerjaSDK.from_ctx(ctx)
if not slug:
return sdk.error("slug wajib diisi", code="MISSING_PARAMETER")
if harga is not None and harga > 100000:
return sdk.bpmn_error("HARGA_MELEBIHI_BATAS", "Harga melebihi batas maksimum")
if sdk.tenant is None or sdk.tenant.id is None:
return sdk.error("svc.tenant.id is required", code="MISSING_CONFIGURATION")
# GET /api/v1/probis/masterdata/{tenantId}/{masterDataSlug}/records
try:
records = sdk.get(
"probis", "masterdata", sdk.tenant.id, slug, "records",
params={
"page": parameters.get("page"),
"page_size": parameters.get("page_size"),
"search": parameters.get("search"),
"order": parameters.get("order"),
"orderBy": parameters.get("orderBy"),
},
)
except AlurkerjaAPIError as exc:
return sdk.error(exc)
return sdk.success(records, message="Master data terbaca")
def main():
"""Main function untuk handle command line arguments"""
parser = argparse.ArgumentParser(
description='Get master data records script - General Action Executor'
)
parser.add_argument(
'--run',
type=str,
required=True,
help='Execution context (JSON file path or JSON string)'
)
args = parser.parse_args()
runkey = ""
# Dicek sebelum try: tanpa SDK, kelas exception di bawah tidak pernah terimpor
if AlurkerjaSDK is None:
print(json.dumps({
"status": "error",
"message": "Package alurkerja-sdk is not installed",
"error": "DEPENDENCY_MISSING",
"runkey": runkey
}, indent=2))
sys.exit(3)
try:
# Parse execution context
if args.run.endswith('.json'):
with open(args.run, 'r') as f:
ctx = json.load(f)
else:
ctx = json.loads(args.run)
runkey = ctx.get("runkey", "")
result = run(ctx)
print(json.dumps(result, indent=2))
sys.exit(exit_code_for(result))
except json.JSONDecodeError as e:
error = {"message": f"Invalid JSON format: {str(e)}", "error": "INVALID_INPUT"}
exit_code = 2
except AlurkerjaConfigError as e:
error = {"message": str(e), "error": "INVALID_CONFIGURATION"}
exit_code = 2
except AlurkerjaRequestError as e:
error = {"message": str(e), "error": "REQUEST_FAILED"}
exit_code = 3
except Exception as e:
error = {"message": f"Error executing get master data records script: {str(e)}", "error": "EXECUTION_ERROR"}
exit_code = 1
print(json.dumps({"status": "error", **error, "runkey": runkey}, indent=2))
sys.exit(exit_code)
if __name__ == "__main__":
main()6.2 Penjelasan Bagian Script
Import dengan fallback. Import SDK dibungkus try/except ImportError. Kalau SDK belum terpasang di host, script tetap bisa mencetak JSON error yang jelas (DEPENDENCY_MISSING, exit code 3) alih-alih traceback Python.
Slug dari process variable. master_data_slug dibaca dari ctx["variables"], yaitu variable proses Camunda yang sudah ada saat Service Task berjalan (mis. diisi dari field form di user task sebelumnya). Paging dan pencarian (page, page_size, search, order, orderBy) tetap dari ctx["parameters"] yang diisi di konfigurasi action pada Service Task. Service Task yang dibuat lewat Studio sudah memanggil putAllProcessVariables(), sehingga seluruh variable proses ikut terkirim ke variables.
Membuat SDK dari ctx. AlurkerjaSDK.from_ctx(ctx) membaca ctx["svc"]. Token, base URL, dan tenant tidak perlu dirakit sendiri. Buat SDK di dalam run(ctx) pada setiap eksekusi — token berumur pendek dan tidak boleh disimpan.
Membentuk response. Balasan script dibuat SDK, bukan dirakit sendiri: sdk.success(...) untuk berhasil, sdk.error(...) untuk gangguan teknis atau validasi, dan sdk.bpmn_error(...) untuk kegagalan bisnis. status, runkey, dan key type diisi otomatis — lihat Bagian 8.4.
Business rule lewat bpmn_error. Batas harga di contoh ini bukan error teknis, melainkan keputusan bisnis: sdk.bpmn_error("HARGA_MELEBIHI_BATAS", ...) membuat Camunda melempar BpmnError, sehingga proses berbelok ke error boundary event berkode HARGA_MELEBIHI_BATAS. Bandingkan dengan sdk.error("slug wajib diisi", ...) di atasnya, yang berakhir sebagai incident di Cockpit.
Error API ditangkap di run. sdk.get(...) melempar AlurkerjaAPIError untuk respons non-2xx; contoh ini menangkapnya dan mengembalikan sdk.error(exc), sehingga error, http_status, dan response terisi sendiri. Kalau tidak ditangkap, exception itu jatuh ke main() dan hasilnya sama.
Membentuk URL. Argumen sdk.get(...) adalah service code diikuti potongan path:
sdk.get("probis", "masterdata", sdk.tenant.id, slug, "records", params={...})
# GET {baseurl}/api/v1/probis/masterdata/1/customers/records?page=0&page_size=10
# Authorization: Bearer <svc.token>
# x-active-tenant: tenant-aSetiap segmen di-URL-encode. Segmen kosong, ., .., atau yang mengandung / ditolak dengan ValueError, sehingga nilai dari parameters tidak bisa membelokkan request ke endpoint lain.
Query params. Nilai None otomatis dibuang, jadi parameter opsional yang tidak diisi (mis. search) tidak ikut terkirim. True/False dikirim sebagai true/false.
Hasil. Respons JSON dikembalikan sebagai dict, lalu dimasukkan ke data pada output script lewat sdk.success(records, ...). Endpoint list master data mengembalikan halaman bergaya Spring: record ada di data.content, total di data.totalElements.
Exit code. sys.exit(exit_code_for(result)) menurunkan exit code dari isi balasan: 0 untuk sdk.success dan sdk.bpmn_error, 1 untuk sdk.error biasa. BPMN_ERROR sengaja 0 — exit non-zero membuat platform menjawab 500 dan Camunda membuat incident sebelum sempat membacanya.
Penanganan error di main(). Yang tersisa di main() hanyalah kegagalan di luar run(ctx) atau yang tidak ditangkap di sana:
| Exception | Kapan | error | Exit code |
|---|---|---|---|
json.JSONDecodeError | --run bukan JSON yang sah | INVALID_INPUT | 2 |
AlurkerjaConfigError | ctx.svc tidak ada / tidak lengkap (dilempar from_ctx) | INVALID_CONFIGURATION | 2 |
AlurkerjaRequestError | Request tidak sampai (koneksi, DNS, timeout) | REQUEST_FAILED | 3 |
Exception lain | Error tak terduga, termasuk ValueError segmen path | EXECUTION_ERROR | 1 |
AlurkerjaAPIError tidak lagi sampai ke sini karena sudah ditangkap di run(ctx).
6.3 Daftarkan Script dan Action di index.json
{
"svc": { "enabled": true },
"scripts": {
"getMasterDataRecords": {
"description": "Membaca record master data tenant aktif via AlurKerja SDK.",
"scripts": {
"type": "python",
"executable": "scripts/get_masterdata_records/get_masterdata_records.py"
}
}
},
"actions": {
"getMasterDataRecords": {
"description": "Read master data records of the active tenant.",
"type": "SCRIPT",
"endpoint": "getMasterDataRecords",
"body": [
{ "key": "page", "value": "0", "type": "number", "required": false },
{ "key": "page_size", "value": "10", "type": "number", "required": false },
{ "key": "search", "value": "", "type": "text", "required": false }
]
}
}
}actions.<nama>.endpoint harus sama dengan key di scripts, dan setiap body[].key menjadi field di ctx["parameters"]. master_data_slug sengaja tidak ada di body karena dibaca dari variable proses, bukan dari parameter action.
6.4 Uji Lokal
Saat dijalankan lokal tidak ada platform yang mengisi svc, jadi isi sendiri di request.example.json. Token bisa diambil dari sesi login user admin SOP (header Authorization di browser devtools).
scripts/get_masterdata_records/request.example.json:
{
"variables": {
"master_data_slug": "customers",
"harga": 75000
},
"parameters": {
"page": 0,
"page_size": 10
},
"configuration": {},
"runkey": "test-get-masterdata-001",
"svc": {
"token": "your_token_here",
"baseurl": "https://onprem.merapi.alurkerja.com",
"tenant": { "id": 1, "name": "Tenant A", "slug": "tenant-a", "uuid": "f8672713-7ec0-4a8a-98ba-f6adf420d105" }
}
}pip install -r requirements.txt
python3 scripts/get_masterdata_records/get_masterdata_records.py \
--run scripts/get_masterdata_records/request.example.jsonContoh output:
{
"status": "ok",
"message": "Master data terbaca",
"data": {
"data": {
"content": [
{ "id": 1, "name": "PT Mitra Sejahtera" }
],
"number": 0,
"size": 10,
"numberOfElements": 1,
"totalElements": 1,
"totalPages": 1,
"first": true,
"last": true,
"empty": false
},
"status": 200,
"message": "Master data records retrieved successfully"
},
"runkey": "test-get-masterdata-001"
}Jangan commit token asli ke request.example.json.
7. Memakai Action di BPMN
- Publish addon yang sudah memuat opt-in
svc(lihat Publish Addon). - Pastikan variable proses
master_data_slugsudah terisi sebelum Service Task tercapai — misalnya dari field form bernamamaster_data_slugdi user task sebelumnya. Contoh ini juga membaca variablehargauntuk business rule batas harga. - Di BPMN editor, pilih Service Task, pilih addon dan action getMasterDataRecords, lalu isi parameter paging/pencarian bila perlu.
- Kalau memakai
sdk.bpmn_errorseperti contoh, pasang error boundary event di Service Task dengan Error Code yang sama persis (HARGA_MELEBIHI_BATAS). Tanpa itu, Camunda membuat incident. - Deploy BPMN dengan akun admin SOP atau owner. Akun inilah yang tokennya dipakai script.
- Jalankan proses. Saat Service Task tercapai, script menerima
ctx.svcdan memanggil master data.
Kalau Save Result diaktifkan, hasil disimpan ke variable proses (default integration_<addon>_<action>_output). Karena output script berbentuk {"data": ...}, isi variable-nya adalah nilai data tersebut — respons dari endpoint master data. Pada contoh di atas, daftar record ada di data.content dari variable itu.
8. Referensi SDK
8.1 Membuat Instance
from alurkerja_sdk import AlurkerjaSDK
sdk = AlurkerjaSDK.from_ctx(ctx) # ctx["svc"], fallback ctx["configuration"]["svc"]
sdk = AlurkerjaSDK(ctx["svc"]) # setara
sdk = AlurkerjaSDK(ctx["svc"], timeout=10) # timeout default 30 detiksvc boleh berupa dict atau string JSON. token dan baseurl wajib; tanpa itu SDK langsung melempar AlurkerjaConfigError.
8.2 Method
| Method | Contoh |
|---|---|
get(service, *path, params=, headers=, timeout=) | sdk.get("probis", "masterdata", sdk.tenant.id, "customers", "records") |
post(service, *path, params=, json=, data=, files=, …) | sdk.post("probis", "masterdata", sdk.tenant.id, "customers", "records", json={"name": "PT A"}) |
put(...) / patch(...) / delete(...) | bentuk sama dengan post |
request(method, service, *path, ...) | method HTTP bebas |
build_url(service, *path) | URL lengkap tanpa query, untuk logging |
params dan json boleh dikirim bersamaan:
# POST /api/v1/probis/masterdata/1/customers/records?source=addon
created = sdk.post(
"probis", "masterdata", sdk.tenant.id, "customers", "records",
params={"source": "addon"},
json={"name": "PT Mitra Sejahtera", "npwp": "01.234.567.8-901.000"},
)8.3 Nilai Kembalian
| Content-Type respons | Hasil |
|---|---|
application/json | dict / list hasil parse |
text/* | str |
| lainnya (mis. unduhan file) | bytes |
| body kosong (mis. 204) | None |
Status non-2xx selalu melempar AlurkerjaAPIError dengan atribut status_code, body, method, dan url.
8.4 Membentuk Response Script
Script tidak perlu merakit dict balasan sendiri. SDK mengisi status, runkey, dan
— untuk kegagalan — key type yang menentukan apa yang terjadi di BPMN.
def run(ctx):
sdk = AlurkerjaSDK.from_ctx(ctx)
slug = ctx.get("parameters", {}).get("slug")
if not slug:
return sdk.error("slug wajib diisi", code="MISSING_PARAMETER")
try:
records = sdk.get("probis", "masterdata", sdk.tenant.id, slug, "records")
except AlurkerjaAPIError as err:
return sdk.error(err) # error, http_status, response terisi sendiri
if records["data"]["totalElements"] == 0:
return sdk.bpmn_error("DATA_KOSONG", f"Master data '{slug}' belum berisi record")
return sdk.success(records, message="Master data terbaca", total=records["data"]["totalElements"])| Method | type | Exit code | Efek di BPMN |
|---|---|---|---|
sdk.success(data=None, message=None, **extra) | — | 0 | Proses lanjut normal |
sdk.error(message_or_exception, code=None, data=None, **extra) | RUNTIME_ERROR | 1 / 2 / 3 | Incident di Cockpit; operator bisa retry activity |
sdk.bpmn_error(code, message=None, data=None, **extra) | BPMN_ERROR | 0 | Camunda melempar BpmnError dengan errorCode = code → ditangkap error boundary event berkode sama |
Bentuk yang dihasilkan:
// sdk.success(records, message="Master data terbaca", total=1)
{ "status": "ok", "message": "Master data terbaca", "data": { "…": "…" }, "total": 1, "runkey": "exec-…" }
// sdk.error("slug wajib diisi", code="MISSING_PARAMETER")
{ "status": "error", "type": "RUNTIME_ERROR", "message": "slug wajib diisi", "error": "MISSING_PARAMETER", "runkey": "exec-…" }
// sdk.error(err) — err: AlurkerjaAPIError 403
{ "status": "error", "type": "RUNTIME_ERROR", "message": "GET … -> HTTP 403: …", "error": "API_ERROR",
"http_status": 403, "response": { "error": "forbidden" }, "runkey": "exec-…" }
// sdk.bpmn_error("STOK_HABIS", "Stok tidak mencukupi", data={"tersedia": 2})
{ "status": "error", "type": "BPMN_ERROR", "error": "STOK_HABIS", "message": "Stok tidak mencukupi",
"data": { "tersedia": 2 }, "runkey": "exec-…" }Catatan:
- Argumen tambahan (
**extra) menambah key di top-level, dan key top-level itulah yang di-merge kevariablesproses. Muatan utama tetap didata. runkeydiisi otomatis kalau SDK dibuat denganAlurkerjaSDK.from_ctx(ctx).- Tersedia juga sebagai fungsi modul —
from alurkerja_sdk import success, error, bpmn_error, exit_code_for— untuk dipakai saat SDK belum sempat dibuat, mis.svctidak lengkap. Di siturunkey=diisi manual. - Di
main(), pakaisys.exit(exit_code_for(result)). - Alias
sdk.bpmnError(...)tersedia supaya penamaannya sama dengan istilah di diagram.
Kapan memakai bpmn_error
sdk.bpmn_error untuk kegagalan bisnis yang alurnya sudah digambar — stok habis,
dokumen ditolak, data tidak ditemukan — sehingga proses berbelok lewat error boundary
event, bukan berhenti sebagai incident.
┌────────────────────┐
│ Service Task │
│ (addon action) │──────▶ lanjut normal (sdk.success)
└─────────┬──────────┘
│ error boundary event, Error Code: STOK_HABIS
▼
┌──────────────┐
│ Task: pesan │ ← sdk.bpmn_error("STOK_HABIS", ...)
│ ke supplier │
└──────────────┘- Error Code di boundary event wajib sama persis dengan
codedi script. Kalau tidak ada boundary event yang cocok, Camunda tetap membuat incident. sdk.bpmn_errormemakai exit code 0 dengan sengaja. Exit non-zero membuat platform menjawab HTTP 500, dan Camunda membuat incident sebelum sempat membacatype-nya.- Variabel hasil disimpan lebih dulu, baru
BpmnErrordilempar. Jadi task di jalur error masih bisa membaca alasan penolakannya dari variable. - Di riwayat eksekusi addon,
BPMN_ERRORtercatat sebagai eksekusi berhasil — script memang selesai; yang terjadi adalah alur berbelok.
Gunakan sdk.error untuk gangguan teknis (API 5xx, koneksi putus, konfigurasi salah):
operator melihatnya sebagai incident dan bisa me-retry setelah penyebabnya beres.
8.5 Endpoint Master Data
Service code probis (bpm-service). {tenantId} = sdk.tenant.id, {slug} = slug master data.
| Operasi | Pemanggilan SDK |
|---|---|
List record (page, page_size, search, order, orderBy) | sdk.get("probis", "masterdata", tid, slug, "records", params={...}) |
| Detail record | sdk.get("probis", "masterdata", tid, slug, "records", record_id) |
| Tambah record | sdk.post("probis", "masterdata", tid, slug, "records", json={...}) |
| Tambah banyak record | sdk.post("probis", "masterdata", tid, slug, "records", "bulk", json=[...]) |
| Ubah record | sdk.put("probis", "masterdata", tid, slug, "records", record_id, json={...}) |
| Hapus record | sdk.delete("probis", "masterdata", tid, slug, "records", record_id) |
Endpoint master data mensyaratkan role admin SOP, itulah alasan deployer wajib admin SOP atau owner.
9. Penolakan dan Troubleshooting
9.1 Penolakan Sebelum Script Dijalankan
Jika syarat svc tidak terpenuhi, integration-service menolak eksekusi dan Service Task menjadi incident di Cockpit dengan body {"error": "...", "addon": "...", "reason": "..."}:
reason | Arti | Tindakan |
|---|---|---|
svc_not_configured | INTEGRATION_AUTH_CLIENT_ID atau PROXY_SERVICE_URL kosong di integration-service | Lengkapi env, restart service |
svc_caller_not_allowed | Action dipanggil bukan dari Service Task (mis. curl dengan token user) | Jalankan dari BPMN |
svc_process_context_missing | Service Task tidak mengirim konteks proses | Deploy ulang BPMN dari Studio terbaru |
svc_process_definition_not_found | Versi BPMN tidak ditemukan | Periksa deployment proses |
svc_process_lookup_failed | Query ke schema camunda gagal | Periksa izin database integration-service |
svc_tenant_mismatch | Proses bukan milik workspace pemanggil | Periksa mapping tenant |
svc_deployer_not_found | User yang men-deploy versi ini tidak tercatat | Deploy ulang BPMN oleh admin SOP |
svc_deployer_not_authorized | Deployer sudah bukan admin SOP/owner atau keluar dari workspace | Deploy ulang BPMN oleh admin SOP aktif, lalu jalankan ulang proses |
svc_token_exchange_failed | Keycloak gagal membuat token | Retry activity; periksa role impersonation service account |
Deploy ulang menghasilkan versi baru. Instance yang sudah berjalan di versi lama tetap memakai deployer versi lama, jadi instance tersebut perlu dijalankan ulang di versi baru.
9.2 Masalah Umum
| Gejala | Penyebab | Solusi |
|---|---|---|
Output DEPENDENCY_MISSING | SDK belum terpasang untuk python3 yang menjalankan script | Pasang SDK (Bagian 3) dengan python3 -m pip |
INVALID_CONFIGURATION: svc tidak ditemukan … | Addon belum opt-in, atau dipanggil lewat jalur API addon | Tambah "svc": {"enabled": true}, publish ulang, jalankan dari Service Task |
Script jalan tetapi svc kosong, tanpa penolakan | Addon terpasang sebelum opt-in ditambahkan, atau integration-service belum versi yang mendukung svc | Publish ulang addon; pastikan integration-service sudah diperbarui |
API_ERROR dengan http_status 403 | Deployer tidak punya akses ke endpoint yang dipanggil | Deploy BPMN dengan akun yang aksesnya sesuai |
API_ERROR dengan http_status 404 | Slug master data atau ID record salah | Periksa nilai variable proses master_data_slug |
EXECUTION_ERROR dengan pesan ... segmen path harus str atau int: None | Variable proses master_data_slug belum terisi saat Service Task berjalan | Isi variable tersebut di langkah sebelumnya (mis. field form) |
| Service task jadi incident padahal ingin berbelok ke jalur error | Script memakai sdk.error, atau kode bpmn_error tidak sama dengan Error Code boundary event | Pakai sdk.bpmn_error("KODE", ...) dengan kode yang sama persis |
Unable to locate package python3.12 di Ubuntu 20.04 | Tidak perlu Python 3.12 | SDK mendukung Python 3.8 bawaan Ubuntu 20.04 |
10. Aturan Keamanan
| Lakukan | Hindari |
|---|---|
Buat AlurkerjaSDK di dalam run(ctx) setiap eksekusi | Menyimpan token ke file, database, atau variable global |
Kirim nilai dari parameters lewat argumen SDK (otomatis di-encode) | Merakit URL sendiri dengan f-string dari input user |
| Kembalikan data bisnis saja di output | Mengembalikan ctx["svc"] atau token di output — output tersimpan di riwayat eksekusi dan variable proses |
Log sdk.process.key / sdk.actor.email untuk tracing | Mencetak token ke stdout/stderr |
