package alga:extension; interface types { record context-data { request-id: option, tenant-id: string, extension-id: string, install-id: option, version-id: option, } enum secret-error { missing, denied, expired, internal, } record http-header { name: string, value: string, } record http-request { method: string, url: string, headers: list, body: option>, } record http-response { status: u16, headers: list, body: option>, } enum http-error { invalid-url, not-allowed, transport, internal, } enum storage-error { missing, conflict, denied, internal, } record storage-entry { namespace: string, key: string, value: list, revision: option, } enum proxy-error { route-not-found, denied, bad-request, internal, } record user-data { tenant-id: string, client-name: string, user-id: string, user-email: string, user-name: string, user-type: string, } record user-data-v2 { tenant-id: string, client-name: string, user-id: string, user-email: string, user-name: string, user-type: string, client-id: option, additional-fields: list>, } enum user-error { not-available, not-allowed, } // Scheduler types for cap:scheduler.manage enum scheduler-error { not-found, validation-failed, quota-exceeded, denied, internal, } record schedule-info { id: string, endpoint-path: string, endpoint-method: string, name: option, cron: string, timezone: string, enabled: bool, payload: option, // JSON-encoded last-run-at: option, last-run-status: option, last-error: option, created-at: option, } record endpoint-info { id: string, method: string, path: string, handler: string, schedulable: bool, } record create-schedule-input { endpoint: string, cron: string, timezone: option, enabled: option, name: option, payload: option, // JSON-encoded } record create-schedule-result { success: bool, schedule-id: option, error: option, field-errors: option, // JSON-encoded map } record update-schedule-input { endpoint: option, cron: option, timezone: option, enabled: option, name: option, payload: option, // JSON-encoded, use empty string to clear } record update-schedule-result { success: bool, error: option, field-errors: option, // JSON-encoded map } record delete-schedule-result { success: bool, error: option, } // Invoicing types for cap:invoice.manual.create enum discount-type { percentage, fixed, } record manual-invoice-item-input { service-id: string, quantity: f64, description: string, rate: f64, is-discount: option, discount-type: option, applies-to-item-id: option, applies-to-service-id: option, } record create-manual-invoice-input { client-id: string, items: list, invoice-date: option, // YYYY-MM-DD due-date: option, // YYYY-MM-DD po-number: option, } record create-manual-invoice-result { success: bool, invoice-id: option, invoice-number: option, status: option, subtotal: option, tax: option, total: option, error: option, field-errors: option, // JSON-encoded map } enum client-read-error { not-allowed, invalid-input, internal, } record client-summary { client-id: string, client-name: string, client-type: option, is-inactive: bool, default-currency-code: option, account-manager-id: option, account-manager-name: option, billing-email: option, } record clients-list-input { search: option, include-inactive: option, page: option, page-size: option, } record clients-list-result { items: list, total-count: u32, page: u32, page-size: u32, } enum service-item-kind { service, product, } enum service-billing-method { fixed, hourly, usage, } enum service-read-error { not-allowed, invalid-input, internal, } record service-summary { service-id: string, service-name: string, item-kind: service-item-kind, billing-method: service-billing-method, service-type-id: option, service-type-name: option, default-rate: f64, unit-of-measure: string, is-active: bool, sku: option, } record services-list-input { search: option, item-kind: option, is-active: option, billing-method: option, page: option, page-size: option, } record services-list-result { items: list, total-count: u32, page: u32, page-size: u32, } record execute-request { context: context-data, http: http-request, } record execute-response { status: u16, headers: list, body: option>, } } interface context { use types.{context-data}; get-context: func() -> context-data; } interface secrets { use types.{secret-error}; get: func(key: string) -> result; list-keys: func() -> list; } interface http { use types.{http-request, http-response, http-error}; fetch: func(request: http-request) -> result; } interface storage { use types.{storage-entry, storage-error}; get: func(namespace: string, key: string) -> result; put: func(entry: storage-entry) -> result; delete: func(namespace: string, key: string) -> result<_, storage-error>; list-entries: func(namespace: string, cursor: option) -> result, storage-error>; } interface logging { log-info: func(message: string); log-warn: func(message: string); log-error: func(message: string); } interface ui-proxy { use types.{proxy-error}; call-route: func(route: string, payload: option>) -> result, proxy-error>; } interface user { use types.{user-data, user-error}; get-user: func() -> result; } interface user-v2 { use types.{user-data-v2, user-error}; get-user: func() -> result; } interface scheduler { use types.{ scheduler-error, schedule-info, endpoint-info, create-schedule-input, create-schedule-result, update-schedule-input, update-schedule-result, delete-schedule-result }; list-schedules: func() -> result, scheduler-error>; get-schedule: func(schedule-id: string) -> result, scheduler-error>; create-schedule: func(input: create-schedule-input) -> create-schedule-result; update-schedule: func(schedule-id: string, input: update-schedule-input) -> update-schedule-result; delete-schedule: func(schedule-id: string) -> delete-schedule-result; get-endpoints: func() -> result, scheduler-error>; } interface invoicing { use types.{create-manual-invoice-input, create-manual-invoice-result}; create-manual-invoice: func(input: create-manual-invoice-input) -> create-manual-invoice-result; } interface clients { use types.{client-read-error, client-summary, clients-list-input, clients-list-result}; list-clients: func(input: clients-list-input) -> result; get-client: func(client-id: string) -> result, client-read-error>; } interface services { use types.{service-read-error, service-summary, services-list-input, services-list-result}; list-services: func(input: services-list-input) -> result; get-service: func(service-id: string) -> result, service-read-error>; } world runner { use types.{execute-request, execute-response}; import context; import secrets; import http; import storage; import logging; import ui-proxy; import user; import user-v2; import scheduler; import invoicing; import clients; import services; export handler: func(request: execute-request) -> execute-response; }