feat(v1.1.9): admin HTTP endpoints — queue triggers + read-only queues

triggers_api.rs adds:
  POST /api/v1/admin/apps/{id}/triggers/queue
    body: { script_id, queue_name, visibility_timeout_secs?,
            dispatch_mode?, retry_max_attempts?, retry_backoff?,
            retry_base_ms? }
    cap: AppManageTriggers
    409-equiv via the repo's "queue 'X' already has a consumer" error
    (TriggerRepoError::Invalid → 422 Invalid in the existing mapping)

queues_api.rs (new) adds read-only inspection endpoints:
  GET /api/v1/admin/apps/{id}/queues
    -> [{queue_name, total, pending, claimed}]

  GET /api/v1/admin/apps/{id}/queues/{queue_name}
    -> {queue_name, total, pending, claimed,
        consumer: Some(QueueConsumer) | None}

  QueueConsumer = { trigger_id, script_id, script_name,
                    visibility_timeout_secs, last_fired_at }

Capability: AppLogRead (same trust tier as execution-log read — these
are read-only operational views, not config changes).

No mutating queue endpoints — enqueue lives on the SDK side; purge /
requeue / delete-message stays at v1.2.

picloud/lib.rs wires the queues router into the guarded /admin chain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-06 22:36:50 +02:00
parent e142d471e1
commit 714f6dae18
4 changed files with 278 additions and 1 deletions

View File

@@ -432,6 +432,8 @@ pub async fn build_app(
config: trigger_config,
master_key: master_key.clone(),
};
// v1.1.9: keep a clone for the queues-api state (built later).
let trigger_repo_for_queues = trigger_repo.clone();
// v1.1.7 public inbound-email receiver. Outside the admin auth layer
// (the URL + per-trigger HMAC secret are the security boundary).
let email_inbound_state = EmailInboundState {
@@ -464,7 +466,7 @@ pub async fn build_app(
max_value_bytes: secrets_max_value_bytes,
};
let apps_state = AppsState {
apps: apps_repo,
apps: apps_repo.clone(),
domains: domains_repo,
routes: route_repo,
domain_table: app_domain_table.clone(),
@@ -513,6 +515,15 @@ pub async fn build_app(
))
.merge(api_keys_router(api_keys_state))
.merge(triggers_router(triggers_state))
.merge(picloud_manager_core::queues_api::queues_router(
picloud_manager_core::queues_api::QueuesState {
queues: queue_repo.clone(),
triggers: trigger_repo_for_queues.clone(),
apps: apps_repo.clone(),
authz: authz.clone(),
scripts: Arc::new(PostgresScriptRepoHandle(script_repo.clone())),
},
))
.merge(files_admin_router(files_admin_state))
.merge(topics_router(topics_state))
.merge(secrets_router(secrets_state))