Files
baya-monorepo/archive/build-chain/contracts/domains/config-reference.md
T
2026-08-02 18:48:32 +03:30

7.4 KiB

Contract — Config, Reference & Platform Signals (backend phase b1)

Admin config/holiday/audit/support-alert endpoints + the current-user notification endpoints. Assumes ../conventions/api-conventions.md + ../conventions/money-and-types.md. Machine schema (authoritative for exact field/param casing): ../openapi/swagger.v1.json.

Status: live as of backend-phase-1 · Frontend consumer: frontend-phase-f14 (notification center) / frontend-phase-f15 (admin config/holidays/audit/alerts)

All responses are the standard OperationResultApiResult envelope (camelCase body, snake_case URLs). Lists carry { items, total, page, pageSize }. Pagination inputs are page (1-based) + pageSize (default 50, max 100) — bound from the query string; derive exact casing from swagger.v1.json.

Enums used

  • config data_type: decimal | int | bool | string | json — how to parse a config value.
  • holiday type: official | religious | national.
  • support-alert type: low_rating | evv_no_show | evv_location_mismatch | verification_expired | payment_anomaly | fraud_signal.
  • support-alert severity: low | medium | high.
  • support-alert status: open | assigned | resolved (forward-only).
  • notification type: open string code the front-end renders/deep-links on (e.g. booking_confirmed); its shape is the data_json contract (below), versioned per type.

Admin — Platform config (platform_config controller, [Authorize(DynamicPermission)])

GET api/v1/platform_config/get_platform_configs

  • Purpose: list config rows. Auth: admin (DynamicPermission). Rate-limited: no.
  • Query: page, pageSize.
  • 200 data: PagedResult<PlatformConfigDto>{ items:[{ key, value, dataType, description }], total, page, pageSize }.

POST api/v1/platform_config/update_platform_config

  • Purpose: update one existing config row; writes an audit_logs entry in the same transaction and evicts the cache. Auth: admin.
  • Body: { "key": "platform_fee_rate", "value": "0.18" }.
  • 200 data: true (empty-body success).
  • Failures: 400 validation (empty key); 404 key does not exist. Notes: value is the raw string parsed per the row's data_type; changing a rate never retroactively re-prices already-computed rows.

GET api/v1/platform_config/get_config_change_history

  • Purpose: the audited change history for one key (from the append-only trail). Auth: admin.
  • Query: key (required), page, pageSize.
  • 200 data: PagedResult<ConfigChangeDto>{ items:[{ id, action, changedFieldsJson, actorUserId, occurredAt }], … }, newest first.

Admin — Holidays (holidays controller, [Authorize(DynamicPermission)])

GET api/v1/holidays/get_holidays

  • Query: from (date, optional), to (date, optional), page, pageSize.
  • 200 data: PagedResult<HolidayDto>{ items:[{ id, holidayDate, nameFa, type, isBankClosed }], … }, by date.

POST api/v1/holidays/upsert_holiday

  • Body: { "holidayDate": "2026-03-21", "nameFa": "نوروز", "type": "national", "isBankClosed": true }.
  • 200 data: true. Failures: 400 (bad type, empty nameFa, default date). Notes: upsert keyed on holidayDate.

POST api/v1/holidays/delete_holiday

  • Body: { "holidayDate": "2026-03-21" }. 200: true; 404 if no holiday on that date.

Admin — Audit (audit controller, [Authorize(DynamicPermission)])

GET api/v1/audit/get_audit_trail

  • Purpose: the immutable trail for one entity. Auth: admin.
  • Query: entity_type (e.g. PlatformConfig), entity_id (string), page, pageSize.
  • 200 data: PagedResult<AuditLogDto>{ items:[{ id, entityType, entityId, action, changedFieldsJson, actorUserId, occurredAt }], … }, newest first. Notes: read-only; there is no write/update/delete endpoint for audit rows.

Admin — Support alerts (support_alerts controller, [Authorize(DynamicPermission)], never user-facing)

GET api/v1/support_alerts/get_support_alerts

  • Query: type?, status?, owner_user_id?, page, pageSize.
  • 200 data: PagedResult<SupportAlertDto>{ items:[{ id, type, severity, status, entityType, entityId, bookingId, reviewId, ownerUserId, resolutionNote, resolvedAt, createdAt }], … }.

POST api/v1/support_alerts/assign_support_alert

  • Body: { "alertId": 42, "ownerUserId": 7 }. 200: true (open → assigned); 404 if missing or already resolved.

POST api/v1/support_alerts/resolve_support_alert

  • Body: { "alertId": 42, "note": "handled" }. 200: true (→ resolved); 404 if missing or already resolved.

Current user — Notifications (notifications controller, [Authorize], tenant-scoped)

Every endpoint is scoped to the signed-in caller (ICurrentUser) — never a body-supplied user id.

GET api/v1/notifications/get_notifications

  • Query: page, pageSize.
  • 200 data: PagedResult<NotificationDto>{ items:[{ id, type, title, body, dataJson, isRead, readAt, createdAt }], … }, unread-first then newest-first.

GET api/v1/notifications/get_unread_count

  • 200 data: { count } — cheap index-backed count for the polling bell.

POST api/v1/notifications/mark_notification_read

  • Body: { "notificationId": 100 }. 200: true; 404 if it isn't the caller's or doesn't exist.

POST api/v1/notifications/mark_all_read

  • No body. 200: true.

Not exposed via REST (internal contracts other backend domains call): CreateNotification (via INotificationDispatcher.DispatchAsync), RaiseSupportAlert (ISupportAlertService.RaiseAsync), EmitSystemEvent (IAnalyticsSink.EmitAsync), WriteAuditLog (IAuditLogger.WriteAsync). The notification retention purge runs on a background hosted service, not an endpoint.

Shared shapes

  • PlatformConfigDto: key (string), value (string, raw — parse per dataType), dataType (enum), description (string, nullable).
  • ConfigChangeDto: id (long), action (created/updated/deleted), changedFieldsJson (string, nullable — { "Field": { "old": …, "new": … } }; encrypted/PII fields redacted as "<redacted>"), actorUserId (int, nullable), occurredAt (UTC ISO-8601).
  • HolidayDto: id (long), holidayDate (date), nameFa (string), type (enum), isBankClosed (bool).
  • AuditLogDto: id (long), entityType (string), entityId (string), action, changedFieldsJson (nullable), actorUserId (nullable), occurredAt.
  • NotificationDto: id (long), type (string code), title (string), body (string, nullable), dataJson (string, nullable — a typed, versioned deep-link payload; shape depends on type, e.g. {"booking_id": 1}), isRead (bool), readAt (UTC, nullable), createdAt (UTC).
  • SupportAlertDto: id, type, severity, status, entityType (string), entityId (string), bookingId (long, nullable), reviewId (long, nullable), ownerUserId (int, nullable), resolutionNote (string, nullable), resolvedAt (UTC, nullable), createdAt (UTC).

Changelog

  • b1 — initial contract (config, holidays, audit, support alerts, notifications).