{
  "schema_version": "1.1",
  "name": "solvotix-agent-entrypoint",
  "language": "en",
  "audience": "autonomous-coding-agent",
  "status": "live",
  "resources": {
    "html_guide": "https://solvotix.net/ai-first/agent-guide",
    "raw_markdown": "https://solvotix.net/ai-first/agent-guide.md",
    "openapi": "https://backend.solvotix.org/v3/api-docs",
    "swagger": "https://backend.solvotix.org/swagger-ui/index.html",
    "api_base": "https://backend.solvotix.org"
  },
  "read_order": [
    "structured_manifest",
    "raw_markdown",
    "openapi",
    "project_local_conventions"
  ],
  "authentication": {
    "provider": "Solvotix API user",
    "identity_type": "machine",
    "scheme": "bearer",
    "token_type": "long-lived tenant-bound API token",
    "token_prefix": "sat_",
    "header": "Authorization",
    "value_format": "Bearer sat_<TOKEN>",
    "runtime_interactive_login_required": false,
    "browser_usage_forbidden": true,
    "create_system_url": "https://portal.solvotix.org/login",
    "create_api_user_url": "https://portal.solvotix.org/home/settings#system-users",
    "plaintext_token_visibility": "creation-or-rotation-response-only"
  },
  "tenant_context": {
    "source": "tenant selected when API user is created",
    "header": "Tenant",
    "header_recommended": true,
    "derived_from_token_when_omitted": true,
    "mismatch_result": "401 Unauthorized",
    "token_belongs_to_tenants": "exactly-one"
  },
  "restricted_role_policy": {
    "restricted": {
      "access_level": "broad-tenant-access-with-sensitive-output-restrictions",
      "access_code_response": "masked-first-and-last-character-visible",
      "mifare_uid_and_credential_id_response": "masked-first-and-last-character-visible",
      "raw_gateway_message_payloads": "removed",
      "gateway_queue_and_message_operations": "403-forbidden",
      "saved_gateway_wifi_operations": "403-forbidden",
      "gateway_denial_retry": "forbidden",
      "receptionist_booking_code_visibility_unchanged": true
    }
  },
  "api_user_role_policy": {
    "storage": "api-user-record",
    "allowed_roles": [
      "Janitor",
      "Cleaning",
      "Receptionist",
      "Restricted",
      "User"
    ],
    "empty_or_missing_roles": "unrestricted-backward-compatible-access",
    "unknown_roles": "400-bad-request-on-create-or-update",
    "enforcement": "same-request-context-and-authorization-as-human-users",
    "changes_effective": "next-authenticated-request-without-token-rotation",
    "management_endpoint": "PUT /api/api-users/{id}/roles",
    "api_user_self_management": false
  },
  "openapi_policy": {
    "authoritative_for": [
      "paths",
      "methods",
      "parameters",
      "request_schemas",
      "response_schemas",
      "documented_status_codes"
    ],
    "on_conflict": "stop-and-report",
    "invent_missing_fields": false
  },
  "physical_command_policy": {
    "http_success_means": "accepted-or-queued",
    "http_success_confirms_physical_completion": false,
    "automatic_retry": false,
    "explicit_exact_pending_retry": "requeue-when-role-generation-and-fingerprint-all-match",
    "verification_sources": [
      "tenant_queue",
      "device_queue",
      "gateway_queue",
      "events",
      "current_device_state"
    ],
    "allowed_reported_states": [
      "requested",
      "queued",
      "delivered",
      "confirmed",
      "failed",
      "unknown"
    ]
  },
  "node_firmware_update_policy": {
    "risk": "operationally-dangerous",
    "approval_required": true,
    "automatic_retry": false,
    "signed_package_activation": {
      "applies_when": "backend-security-record-indicates-node-holds-trust-anchor",
      "firmware_bundle_files": [
        "/firmware/nrf_node-<version>.bin",
        "/firmware/nrf_node-<version>.manifest.bin",
        "/firmware/nrf_node-<version>.manifest.sig",
        "/firmware/nrf_node-<version>.signer.der"
      ],
      "catalog_visibility": "only-complete-four-file-bundles",
      "release_signing_location": "offline-trusted-operator-computer",
      "backend_private_signing_key_required": false,
      "backend_startup_requires_signing_private_key": false,
      "backend_startup_requires_signing_certificate": false,
      "signing_certificate_source": "adjacent-per-release-signer.der",
      "backend_bundle_verification": [
        "manifest-format-and-algorithms",
        "exact-image-size",
        "filename-firmware-version",
        "target-node-type-or-explicit-any",
        "image-sha256",
        "per-release-signer-chain",
        "rsa-signature-with-per-release-public-code-signing-certificate"
      ],
      "backend_forwards_presigned_metadata_without_modification": true,
      "manifest_format": 1,
      "manifest_binds": [
        "image_sha256",
        "exact_image_size",
        "firmware_version",
        "target_node_type"
      ],
      "signature": "rsa-2048-pkcs1-v1_5-sha256",
      "certificate_requirements": [
        "leaf-ca-false",
        "digital-signature-key-usage",
        "code-signing-extended-key-usage",
        "leaf-issued-by-delivered-intermediate",
        "chain-terminates-at-node-stored-root"
      ],
      "activation_gate": "node-verifies-staged-image-digest-manifest-certificate-roles-chain-and-signature-before-marking-mcuboot-slot",
      "transport_encryption_independent": true,
      "signing_failure_behavior": "missing-or-invalid-bundle-or-public-verification-material-fails-closed-without-unsigned-fallback",
      "rootless_recovery_behavior": "legacy-unsigned-ota-remains-available"
    },
    "smart_lock_code_storage_transition": {
      "boundary_firmware_version": 111,
      "upgrade_from_legacy": {
        "automatically_migrated_slots": "1-987",
        "slots_requiring_repush": "988-1980"
      },
      "downgrade_to_legacy": {
        "stored_codes_seen_by_legacy_firmware": "empty",
        "codes_requiring_repush": "all",
        "legacy_code_save_effect": "can-overwrite-firmware-111-certificate-and-session-storage",
        "communication_after_authorized_session_retirement": "legacy-plaintext-node-protocol"
      },
      "operator_warning_required": true,
      "code_resynchronization_plan_required": true
    },
    "per_node_queue_isolation": true,
    "allowed_packages_during_active_update": [
      "firmware_update",
      "firmware_update_chunk",
      "firmware_update_chunk_done"
    ],
    "allowed_action_ids_during_active_update": [
      21,
      22,
      23
    ],
    "new_non_ota_packages_during_active_update": "rejected-before-queue-insertion-and-persistence",
    "regular_packages_during_active_update": "remain-queued-until-update-finishes-or-is-aborted",
    "ota_precedes_earlier_regular_packages_for_same_node": true,
    "unencrypted_chunk_confirmation": "positive-device-ble-acknowledgement-relayed-as-gateway-status-2-for-exact-message-id",
    "encrypted_chunk_confirmation": "positive-device-ble-acknowledgement-relayed-as-gateway-status-2-for-exact-message-id",
    "encrypted_transport_ack_effect": "remove-exact-queued-chunk-advance-progress-and-refill-window",
    "encrypted_transport_pipeline_window": 8,
    "minimum_inter_chunk_delay_ms": 250,
    "authenticated_action_46_effect": "audit-signal-and-idempotent-delivery-fallback",
    "secure_to_legacy_downgrade": {
      "secure_protocol_minimum_firmware_version": 111,
      "authorization": "persist-exact-requested-legacy-version-before-secure-ota-queueing",
      "ota_transport": "existing-authenticated-secure-session-plus-release-signature-chain-to-node-stored-root",
      "gateway_status_2_effect": "advance-ota-transport-progress-without-retiring-secure-session",
      "session_retirement": [
        "authenticated-action-46-for-exact-secure-finalize-message",
        "positive-secure-finalize-transport-delivery-then-post-reboot-advertisement-exactly-matching-persisted-downgrade-target"
      ],
      "advertisement_flag_alone_authorizes_downgrade": false,
      "mismatched_or_unsolicited_legacy_advertisement": "security-mismatch-no-plaintext-fallback",
      "post_retirement_transport": "legacy-plaintext-node-protocol",
      "abort_effect": "clear-downgrade-authorization-and-preserve-active-secure-session"
    },
    "missing_transport_confirmation": "retain-same-logical-chunk-for-bounded-internal-transport-retry",
    "node_originated_response_retirement": "gateway-transport-acknowledgement-without-backend-action-46-during-ota",
    "authenticated_bad_state_recovery": "discard-current-window-and-restart-same-transfer-from-authenticated-start",
    "cancellation_endpoint": "DELETE /api/node-updates/sensors/{sensorId}",
    "cancellation_idempotency": "always-200-with-removed-ota-package-count-including-zero",
    "cancellation_scope": "tenant-scoped-session-ota-queue-in-flight-and-progress-state",
    "concurrent_start_behavior": "409-without-modifying-running-update",
    "generic_queue_delete_during_ota": "409-without-modifying-queue",
    "other_nodes_affected": false
  },
  "node_certificate_rotation_policy": {
    "default_enabled": false,
    "availability": "not-registered-returns-404-unless-solvotix.security.rotation-api.enabled-is-true-at-backend-startup",
    "maintenance_window_reenable": "set-property-true-restart-perform-approved-operation-set-false-restart",
    "public_integration_endpoints": {
      "operational": "POST /api/node-security/sensors/{sensorId}/operational-certificate-rotation",
      "session_key": "POST /api/node-security/sensors/{sensorId}/session-key-rotation",
      "root": "POST /api/node-security/sensors/{sensorId}/root-certificate-rotation"
    },
    "authentication": "bearer-token-with-auth-filter-tenant-context",
    "request_body": null,
    "root_request_body": "exactly-one-pem-ca-transition-certificate-signed-by-current-root-no-private-key",
    "accepted_response": "202-queued-not-installed",
    "risk": "security-sensitive",
    "approval_required": true,
    "automatic_retry": false,
    "transport_action": 47,
    "encrypted_fragment_der_payload_max_bytes": 177,
    "result_sub_action": 4,
    "requires_active_authenticated_session": true,
    "gateway_route_requirement": "known-tenant-scoped-route-persistent-queue-may-wait-for-live-gateway-readiness",
    "signed_generation_source": "non-zero-unsigned-32-bit-certificate-serial",
    "replacement_generation_rule": "strictly-greater-than-persisted-generation",
    "equal_generation_rule": "idempotent-only-when-fingerprint-identically-matches-installed-certificate",
    "fragment_retirement": "exact-authenticated-action-46-acknowledgement",
    "installation_confirmation": [
      "role",
      "generation",
      "sha256_fingerprint",
      "success_status"
    ],
    "operational_confirmation_fallback": "exact-pending-generation-and-fingerprint-plus-mutually-confirmed-replacement-session",
    "interrupted_session_confirmation_recovery": "repeat-session-key-endpoint-resends-persisted-pending-key-confirmation-with-new-sequence-and-does-not-restart-certificate-rotation",
    "node_duplicate_confirmation_behavior": "idempotently-answer-valid-backend-confirmation-for-current-active-key-including-after-reboot",
    "confirmation_mismatch": "retain-pending-state-and-record-security-error",
    "success_verification": "pending-state-clears-only-after-exact-authenticated-installation-result",
    "operational_rotation": "intermediate-and-operational-certificate-single-tracked-transaction-followed-by-fresh-enrollment",
    "session_key_rotation": "idempotent-current-operational-certificate-reassertion-followed-by-node-generated-session-and-atomic-confirmed-promotion",
    "session_key_completion_verification": "device-security-session-generation-increases",
    "session_key_fingerprint_mismatch": "409-rotate-operational-certificate-first",
    "ota_signer_policy": "pin-first-valid-signer-and-require-higher-signed-generation-for-replacement"
  },
  "smart_lock_slot_allocation": {
    "scope": "per-lock",
    "concurrency": "serialized-within-single-runner-process",
    "duplicate_slot_allocation_from_concurrent-runner-requests": "prevented",
    "pending_upload_recovery": {
      "source": "previously-accepted-adding-to-lock-slot",
      "schedule": "five-minute-monitor",
      "missing_command_minimum_pending_age_seconds": 60,
      "slot_repair_rebuilds_affected_pending_commands_immediately": true,
      "repairs_duplicate_or_invalid_pending_slot_numbers": true,
      "preserves_uploaded_slot_numbers": true,
      "requeues_only_when_equivalent-add-command-is-absent": true,
      "requeues_missing-remove-commands": true,
      "remove_recovery_preserves_slot_and_upload_timestamp": true,
      "remove_recovery_requires_equivalent-remove-command-to-be-absent": true,
      "authorizes_new_access_code": false,
      "confirms_physical_delivery": false
    },
    "changes_command_idempotency": false,
    "confirms_physical_delivery": false
  },
  "direct_package_delivery_policy": {
    "endpoint": "POST /api/relay/{relayId}/package",
    "supported_operations": [
      "open",
      "close",
      "pulse",
      "consumption"
    ],
    "consumption_input": {
      "field": "kwh",
      "unit": "kilowatt-hour",
      "conversion": "round-half-up(kwh * configured-cf-pulses-per-kwh)",
      "configuration": "relay.metering.cf-pulses-per-kwh",
      "default_pulses_per_kwh": 2175856,
      "default_basis": "BL0937B reference circuit with 1mOhm shunt, 6x200kOhm high-side divider, 510Ohm low-side resistor, and nominal 1.1V reference",
      "result_range": "unsigned-32-bit",
      "response_audit_field": "consumptionPulseCount",
      "zero_behavior": "cancel-active-countdown-and-close-relay"
    },
    "http_success_means": "package-generated-only",
    "backend_queue_created": false,
    "backend_event_created": false,
    "approval_required_before_delivery": true,
    "automatic_retry_generation": "allowed-only-before-any-delivery-attempt",
    "automatic_retry_delivery": false,
    "verification_sources": [
      "transport-acknowledgement",
      "device-acknowledgement",
      "current-device-state"
    ]
  },
  "manual_queue_transfer_policy": {
    "endpoint": "GET /api/gateways/queue/device/{deviceId}/packages",
    "tenant_scoped": true,
    "queue_order_preserved": true,
    "download_mutates_queue": false,
    "package_encodings": [
      "base64",
      "uppercase-hex"
    ],
    "delivery_approval": "inherit-from-queued-operation",
    "automatic_retry_download": "allowed-before-delivery",
    "automatic_retry_delivery": false,
    "remove_after_positive_device_acknowledgement": "DELETE /api/gateways/queue/message/{messageId}",
    "package_payload_logging": "forbidden"
  },
  "node_core_package": {
    "total_bytes": 212,
    "fields": [
      {
        "offset": 0,
        "length": 6,
        "name": "message_id",
        "encoding": "raw-bytes"
      },
      {
        "offset": 6,
        "length": 2,
        "name": "timestamp",
        "encoding": "unsigned-16-bit-little-endian-unix-seconds-low-bits"
      },
      {
        "offset": 8,
        "length": 1,
        "name": "action",
        "encoding": "unsigned-byte"
      },
      {
        "offset": 9,
        "length": 1,
        "name": "sub_action",
        "encoding": "unsigned-byte"
      },
      {
        "offset": 10,
        "length": 201,
        "name": "data",
        "encoding": "operation-specific-zero-padded"
      },
      {
        "offset": 211,
        "length": 1,
        "name": "checksum",
        "encoding": "xor-of-bytes-0-through-210"
      }
    ],
    "transport_contract_included": true,
    "transport_requirement": "follow-tested-mobile-ble-contract-in-agent-guide-section-17.3",
    "ble_transport": {
      "manufacturer_id": "0x79fd",
      "expected_local_name": "SVN",
      "local_name_required": false,
      "service_uuid": "12345678-1234-5678-1234-56789abcdef0",
      "write_characteristic_uuid": "12345678-1234-5678-1234-5678efbeadde",
      "preferred_write_mode": "write-without-response",
      "maximum_chunk_bytes": 215,
      "chunk_size_formula": "max(20,min(215,negotiated-mtu-3))",
      "default_chunk_bytes_when_mtu_unavailable": 20,
      "continuous_scan": true,
      "duplicate_advertisements": true,
      "nearby_stale_after_seconds": 10,
      "backend_online_status_controls_ble_nearby": false,
      "stop_scan_before_connect": true,
      "resume_scan_after_disconnect": true,
      "automatic_retry_after_delivery_attempt": false
    },
    "downloaded_package_mutation": "forbidden"
  },
  "mews_cleaning_sync_policy": {
    "endpoint": "POST /integrations/mews/cleaning/sync",
    "direction": "mews-to-built-in-cleaning-only",
    "master": "mews",
    "authentication": "authenticated-provider-integration-request",
    "tenant_header_required": true,
    "request_body": false,
    "success_status": 204,
    "state_mapping": {
      "Clean": "cleaned",
      "Inspected": "cleaned",
      "Dirty": "dirty",
      "OutOfService": "no-change",
      "OutOfOrder": "no-change"
    },
    "risk_class": "reversible",
    "approval_required": false,
    "idempotent": true,
    "automatic_retry": "allowed-after-definite-failure-no-concurrent-runs",
    "verification": [
      "GET /api/cleaning/rooms",
      "GET /api/cleaning/rooms/{roomId}"
    ],
    "automatic_sources": [
      "service-startup",
      "five-minute-reconciliation",
      "mews-resource-websocket-when-available"
    ]
  },
  "mews_booking_sync_policy": {
    "endpoint": "POST /integrations/mews/sync",
    "authentication": "bearer-plus-tenant-context",
    "tenant_header_required": true,
    "request_body": false,
    "optional_query_parameters": {
      "updatedSince": "ISO-8601 timestamp; omitted or invalid uses the configured lookback; effective start is capped to 48 hours before now",
      "updatedTo": "ISO-8601 timestamp; omitted or invalid uses now; future values are capped to now"
    },
    "selection": [
      "reservations updated within the effective interval of at most the last 48 hours",
      "reservations colliding with the tenant-local current calendar day regardless of last update time"
    ],
    "deduplication_key": "Mews reservation ID",
    "success_status": 202,
    "missing_settings_status": 400,
    "disabled_or_incomplete_settings": "accepted-no-op",
    "risk_class": "state-changing-reversible",
    "approval_required": false,
    "approval_precondition": "tenant has already configured Mews as its booking provider",
    "idempotency": "provider-ID upsert; canceled provider reservations are removed; duplicate selections are applied once per run",
    "automatic_retry": "allowed-after-definite-failure-no-concurrent-runs",
    "verification": "GET /api/bookings and confirm dates, room, guest, payment, and stay state before downstream physical-access reliance",
    "physical_operation_safety": "booking changes can affect downstream room-code, messaging, cleaning, and access workflows"
  },
  "mews_cleaning_early_access_handoff": {
    "endpoint": "POST /api/internal/cleaning/rooms/{roomId}/apply-early-access",
    "visibility": "private-process-to-process",
    "authentication": "shared-internal-token",
    "tenant_context_required": true,
    "request_body": false,
    "success_status": 204,
    "trigger": "after-successfully-applied-or-confirmed-mews-clean-or-inspected-state",
    "effect": "evaluate-existing-runner-early-access-rule",
    "changes_cleaning_state": false,
    "retry": "next-full-mews-reconciliation-after-failure",
    "public-api-token-use": "forbidden"
  },
  "booking_arrival_tracking_policy": {
    "read_endpoint": "GET /api/bookings",
    "state_field": "arrived",
    "timestamp_field": "arrivedAt",
    "trigger": "first-valid-use-of-booking-room-code",
    "timestamp_source": "lock-event-unix-seconds-with-server-time-fallback",
    "overwrite_on_later_code_use": false,
    "client_writable": false,
    "check_in_undo_behavior": "3rpms-undo-clears-arrived-and-arrivedAt",
    "verification": "GET /api/bookings",
    "asynchronous": true,
    "physical_arrival_proof": "arrival-event-observed-not-guaranteed-physical-presence",
    "approval_required": false
  },
  "guest_code_publication_policy": {
    "guest_delivery_verification": "GET /api/automation/messages/logs/bookings/{bookingId}",
    "authentication": "bearer-plus-tenant-context",
    "required_role": "Receptionist",
    "automation_publication_gate": "successful-guest-email-or-sms-containing-current-code-or-matching-tenant-booking-portal-url-or-successful-whatsapp-with-either-in-rendered-sms-text",
    "matching_guest_portal_url_qualifies_as_code_content": true,
    "guest_portal_requires_current_booking_code": true,
    "unsent_fallback_text_is_delivery_proof": false,
    "rendered_sms_text_is_code_content_evidence_for_delivered_whatsapp": true,
    "delivered_whatsapp_booking_portal_qualifies": true,
    "code_sent_timestamp_proves_source_publication": false,
    "code_assignment_response_proves_source_publication": false,
    "activation_precondition": "tenant-pms-module-and-provider-integration-enabled-with-configured-credentials",
    "deduplication_scope": "booking-and-unchanged-code-where-supported-by-provider-adapter",
    "concurrency_control": "durable-claim-where-supported-by-provider-adapter",
    "ambiguous_publication_retry": "operator-reconciliation-before-retry",
    "resend_guest_message_to_retry_publication": false,
    "automatic_reconciliation_guaranteed": false,
    "source_verification": "confirm-access-key-attached-to-intended-booking-in-source-system",
    "physical_access_proof": false,
    "risk": "security-sensitive-access-credential-disclosure",
    "guest_delivery_approval_required": true
  },
  "guest_portal_button_policy": {
    "syntax": "{guestportalbutton=\"Open guest portal\", color=\"#1068F0\", textColor=\"#F8F8F8\"}",
    "default_label": "Open guest portal",
    "default_background": "#1068F0",
    "default_text": "#F8F8F8",
    "light_background_text": "#001838",
    "custom_color_formats": [
      "#RGB",
      "#RRGGBB"
    ],
    "invalid_color_behavior": "default-background",
    "text_color_parameter": "textColor",
    "text_color_formats": [
      "#RGB",
      "#RRGGBB"
    ],
    "missing_or_invalid_text_color_behavior": "automatic-text-color-for-background",
    "color_parameter_order": "color before textColor when both are supplied",
    "missing_booking_or_tenant_behavior": "leave-placeholder-unchanged",
    "malformed_token_behavior": "leave-placeholder-unchanged",
    "email_output": "HTML-escaped label in a styled anchor to the existing guest-portal booking URL",
    "sms_and_subject_output": "button-token-unchanged-use-guestportal-for-plain-url",
    "placement": "email body only; standalone content, never inside an HTML tag or existing link",
    "supports_room_instructions_and_manual_overrides": true,
    "existing_guestportal_token_unchanged": true,
    "approval": "recipient/content approval before configuration changes or sending",
    "verification": "message-preview before sending; booking message logs after dispatch",
    "delivered_button_qualifies_as_guest_portal_code_content": true,
    "changes_authorization_validity_or_retry_policy": false
  },
  "arrival_message_eligibility_policy": {
    "trigger_key": "when_start_time_has_passed",
    "configuration_endpoint": "POST /api/automation/messages/triggers",
    "authentication": "bearer-plus-tenant-context",
    "eligibility": "start-plus-offset-minutes-reached-and-not-checked-out-and-end-not-reached-if-present",
    "update_endpoint": "PUT /api/automation/messages/triggers/{id}",
    "offset_minutes": {
      "field": "offsetMinutes",
      "type": "integer",
      "default": 0,
      "omitted_or_null_on_create_or_update": 0,
      "existing_trigger_default": 0,
      "negative": "minutes-before-booking-start",
      "positive": "minutes-after-booking-start",
      "time_semantics": "elapsed-minutes",
      "other_trigger_types": "ignored",
      "changes_can_make_unsent_bookings_immediately_eligible": true,
      "extends_booking_end_or_checkout_cutoff": false,
      "exact_delivery_time_guaranteed": false
    },
    "early_reservations": "wait-until-booking-start-plus-offset-minutes",
    "late_reservations": "evaluate-immediately-on-import-or-update-while-active",
    "periodic_reevaluation": "normally-about-once-per-minute",
    "booking_creation_cutoff": false,
    "rule_modification_cutoff": false,
    "existing_recipient_payment_cleanliness_gates_apply": true,
    "editing_wording_resends_delivered_channels": false,
    "editing_offset_resends_delivered_channels": false,
    "deduplication": "existing-trigger-booking-code-delivered-channels",
    "new_trigger_can_message_existing_active_bookings": true,
    "approval_required": true,
    "ambiguous_create_retry": "read-configured-triggers-before-retrying",
    "verification": "GET /api/automation/messages/logs/bookings/{bookingId}"
  },
  "booking_check_in_code_publication_policy": {
    "read_endpoint": "GET /integrations/booking-filters",
    "write_endpoint": "POST /integrations/booking-filters",
    "authentication": "authenticated-integration-service-session-cookie-or-accepted-bearer-identity-token",
    "main_api_machine_token_support_assumed": false,
    "tenant_header_required": true,
    "filter_type": "push_codes_on_check_in",
    "variables": {},
    "enabled_by": "filter-presence",
    "default_enabled": false,
    "automatic_installation": false,
    "scope": "supporting-provider-adapters-only",
    "prerequisites": "enabled-pms-module-and-provider-with-credentials-current-persisted-code-checked-in-not-checked-out",
    "guest_delivery_required_for_check_in_path": false,
    "message_delivery_is_independent_publication_trigger": true,
    "qualifying_message_content": "current-room-code-or-matching-booking-guest-portal-url",
    "evaluation": "message-delivery-callback-independently-and-booking-sync-or-supported-code-use-check-in-when-push-codes-on-check-in-filter-is-present",
    "save_itself_publishes_codes": false,
    "existing_checked_in_bookings_eligible_on_next_sync": true,
    "write_semantics": "replace-complete-list-preserve-unrelated-filters",
    "removal": "stops-future-check-in-triggered-attempts-but-not-message-triggered-publication-and-does-not-revoke-attachments-or-cancel-in-flight-requests",
    "deduplication": "durable-booking-and-current-code-claim-confirmed-push-not-repeated",
    "ambiguous_publication_retry": "operator-reconciliation-required",
    "automatic_retry_of_filter_save": false,
    "ambiguous_save": "read-back-before-replacing-again",
    "success_status": 200,
    "invalid_input_or_missing_tenant_status": 400,
    "invalid_or_missing_authentication_status": 401,
    "risk": "security-sensitive-access-credential-disclosure",
    "approval_required": true,
    "verification": "read-local-booking-state-and-confirm-attachment-in-source-system",
    "physical_access_proof": false
  },
  "booking_expiry_checkout_policy": {
    "read_endpoint": "GET /integrations/booking-filters",
    "write_endpoint": "POST /integrations/booking-filters",
    "authentication": "authenticated-integration-service-session-cookie-or-accepted-bearer-identity-token",
    "main_api_machine_token_support_assumed": false,
    "tenant_header_required": true,
    "tenant_body_or_query_argument": false,
    "filter_type": "checkout_after_end",
    "enabled_variables": {
      "value": true
    },
    "default_enabled": false,
    "automatic_installation": false,
    "manual_operator_configuration_required": true,
    "eligibility": "supported-source-provider-and-previously-checked-in-and-booking-end-reached",
    "guest_portal_checkout_requires_filter": false,
    "guest_request_retries_require_filter": false,
    "expiry_request_retries_require_filter": true,
    "legacy_expiry_requests_require_filter": true,
    "removal": "stops-future-expiry-dispatch-and-retry-does-not-undo-in-flight-request",
    "write_semantics": "replace-complete-list-and-reapply-existing-filters-to-stored-bookings",
    "preserve_unrelated_filters": true,
    "success_status": 200,
    "invalid_value_or_missing_tenant_status": 400,
    "invalid_or_missing_authentication_status": 401,
    "risk": "high-impact-reservation-checkout-and-potential-access-expiry",
    "approval_required": true,
    "automatic_retry_of_filter_save": false,
    "ambiguous_save": "read-back-before-replacing-again",
    "enabling_applies_to_already_expired_checked_in_bookings": true,
    "physical_code_lifecycle_is_independent": true,
    "verification": "confirm-checkout-in-source-provider-local-state-and-events-alone-are-insufficient"
  },
  "booking_room_code_recovery_policy": {
    "code_picker_strategy": "all",
    "grace_filter_required_for_retention": false,
    "association_retention_cutoff": "next-successful-monitor-sweep-at-or-after-stored-end-plus-seven-24-hour-days",
    "retained_after_checkout_and_expiry": true,
    "assignment_changes": "seven-day-expiry-cleanup; room-change; explicit-code-replacement; booking-deletion",
    "physical_deactivation": "existing-checkout-end-time-and-optional-grace-policy",
    "checked_out_still_deactivates_lock_credentials": true,
    "pool_shortage_keeps_inactive_code_uploaded": false,
    "automatic_lifecycle_releases_inactive_code_to_available_pool": false,
    "automatic_generation_excludes_retained_booking_codes": true,
    "eligible_reactivation": "reuse-retained-code-and-queue-upload-under-existing-access-window-policy",
    "conflict_handling": "skip-recovery-if-code-belongs-to-another-room-or-taken-entry-belongs-to-another-booking",
    "guest_checkout_protection": "existing-inbound-snapshot-reopening-rules-still-apply",
    "historical_code_backfill": false,
    "already_assigned_replacement_code_rollback": false,
    "new_endpoint_or_request_field": false,
    "reactivation_approval": "explicit-operator-intent-for-physical-access-change",
    "verification": "booking-state-and-code; room-code-health-and-credential-lifecycle-events; queued-command-is-not-device-confirmation",
    "association_retention_days": 7,
    "retention_clock": "stored-booking-end-not-checkout-time",
    "cleanup_requires": "access-inactive; room-inventory-code-absent; recorded-room-lock-credential-absent-or-removed; unchanged-booking-room-code-dates-and-check-in-out-status",
    "cleanup_unknown_state": "retain-if-end-or-room-missing-or-assigned-device-unresolved",
    "cleanup_event": "booking-updated-with-roomCode-absent; historical-event-snapshots-retained",
    "after_cleanup_reactivation": "normal-code-selection-policy-unless-an-unambiguous-room-owned-reservation-can-be-restored-under-active-grace-policy",
    "room_owned_association_recovery": {
      "grace_filter_required": true,
      "code_picker_strategy": "all-including-disabled-random-generation",
      "order": "before-orphan-pool-cleanup-and-normal-code-backfill",
      "preconditions": "missing-booking-code; exactly-one-valid-taken-room-code-owned-by-booking; complete-dates; shared-access-policy-still-active",
      "checked_in_required": false,
      "unchecked_in_requires_start_passed": true,
      "checked_out_or_expired_guest_report": "do-not-restore-or-reactivate",
      "conflicts": "skip-other-room-or-other-booking-code-reservations-and-ambiguous-owned-codes",
      "write": "set-roomCode-only-if-id-room-dates-check-in-out-guest-report-and-missing-code-snapshot-still-match",
      "unresolved_eligible_owned_reservation": "protect-from-orphan-pool-rotation-and-do-not-take-replacement-pool-code",
      "historical_pin_inference": false,
      "verification": "read-booking-roomCode-then-room-code-health-and-device-credential-events; queued-upload-is-not-physical-confirmation"
    }
  },
  "booking_code_activity_warning_policy": {
    "endpoint": "GET /api/bookings/bookings",
    "authentication": "bearer-plus-tenant-header",
    "required_role": "RECEPTIONIST",
    "field": "roomCodeActiveAfterCheckout",
    "read_only": true,
    "persisted": false,
    "nullable": true,
    "computed_in_other_booking_operations": false,
    "true_requires": "stored-end-strictly-passed-and-any-assigned-code-capable-room-lock-records-known-booking-PIN-as-added-or-pending-removal-with-confirmed-upload-timestamp",
    "independent_of": [
      "checkedIn",
      "checkedOut",
      "grace-filter",
      "grace-days",
      "lock-connectivity"
    ],
    "missing_booking_code": "read-only-fallback-to-taken-room-codes-explicitly-owned-by-booking",
    "false": "end-missing-or-not-passed; no-recorded-presence-for-known-code",
    "unknown": "null-or-omitted-for-overdue-unresolvable-room-device-locks-unconfirmed-slot-state-or-read-failure",
    "unknown_is_confirmed_removal": false,
    "hardware_semantics": "stored-device-reports-not-live-probe-or-proof-of-physical-access",
    "existing_list_filters_unchanged": true,
    "risk": "low-read-only",
    "approval_required": false,
    "idempotent": true,
    "retry": "safe-status-read-after-transient-failure",
    "side_effects": "none-no-device-provider-command-or-new-event",
    "verification": "refresh-booking-list-after-state-changes; room-code-health-and-credential-events-for-per-lock-details"
  },
  "booking_message_log_policy": {
    "endpoint": "GET /api/automation/messages/logs/bookings/{bookingId}",
    "authentication": "bearer-plus-tenant-context",
    "tenant_header_required": true,
    "tenant_argument_allowed": false,
    "required_role": "Receptionist",
    "read_only": true,
    "idempotent": true,
    "automatic_retry": "allowed-after-definite-transport-failure",
    "approval_required": false,
    "ordering": "createdAt-descending",
    "empty_result": "unknown-booking-or-no-successful-delivery-logs",
    "sensitive_fields": [
      "recipientEmail",
      "recipientPhone",
      "recipientKey",
      "emailBody",
      "smsBody",
      "roomCode"
    ],
    "delivery_verification": "expected-channel-present-in-channels",
    "trigger-fired-is-delivery-proof": false,
    "queue": false,
    "physical_operation": false
  },
  "sensor_deletion_policy": {
    "endpoint": "DELETE /api/sensor/{id}",
    "authentication": "bearer-with-auth-filter-tenant-context",
    "roles": "unrestricted-or-Restricted",
    "risk": "destructive-and-ownership-changing",
    "approval_required": true,
    "preconditions": [
      "confirm-current-owning-tenant",
      "confirm-device-id-and-current-inventory"
    ],
    "request_body": null,
    "success": "204-no-content-including-already-absent",
    "cleanup": [
      "global-sensor-security-association",
      "tenant-sensor-record",
      "all-device-backend-code-slot-records"
    ],
    "physical_credentials_erased": false,
    "commands_queued": false,
    "existing_commands_cancelled": false,
    "room_and_lock_user_references_removed": false,
    "deletion_event_emitted": false,
    "transactional": false,
    "idempotency": "only-while-device-remains-unclaimed-and-unchanged",
    "automatic_retry": false,
    "failure_recovery": "inspect-inventory-and-ownership-before-authorized-retry-do-not-delete-a-new-claim",
    "verification": "device-id-absent-from-GET-/api/sensor",
    "errors": {
      "401": "authentication-or-api-token-tenant-mismatch",
      "403": "role-denied"
    },
    "delayed_code_warning_policy": {
      "missing_devices": "exclude-orphaned-slots-without-deleting-them",
      "existing_devices": "existing-warning-delay-and-tenant-24-hour-limit"
    }
  },
  "sensor_measurement_decoding_policy": {
    "read_endpoint": "GET /api/sensor",
    "raw_field": "adv_data.sensor_data",
    "raw_encoding": "uppercase-hex-three-bytes-byte-0-first",
    "temperature": {
      "source_bytes": [
        0,
        1
      ],
      "encoding": "signed-16-bit-little-endian-hundredths-celsius",
      "formula": "celsius = int16le(byte0, byte1) / 100",
      "no_reading_marker": "FFFF",
      "decoded_by_backend": true,
      "decoded_field": "temperatureC",
      "decoded_unit": "celsius",
      "no_reading_value": "NaN-serialized-as-string",
      "no_reading_handling": "treat-as-absent-never-as-zero",
      "reporting_node_types": [
        4,
        11
      ],
      "reporting_sensor_types": [
        "temperature",
        "wall_thermostat"
      ]
    },
    "humidity": {
      "source_bytes": [
        2
      ],
      "encoding": "unsigned-byte-whole-percent",
      "range": [
        0,
        100
      ],
      "decoded_by_backend": false,
      "client_must_decode": true,
      "history_stored": false,
      "aggregated": false
    },
    "state_nodes": {
      "sensor_types": [
        "relay",
        "high_voltage_relay"
      ],
      "byte_0": "open-state-00-closed-01-open",
      "unused_bytes": [
        1,
        2
      ]
    },
    "lock_open_state": {
      "sensor_types": [
        "lock_8015",
        "lock_s42",
        "lock_controller",
        "lock_wireless_code_panel"
      ],
      "raw_field": "adv_data.node_settings",
      "raw_encoding": "uppercase-hex-three-bytes-byte-0-first",
      "source_byte": 0,
      "mask": "0x10",
      "set_when": "held-open-with-no-scheduled-close",
      "held_open_causes": [
        "backend-open",
        "forced-open",
        "system-menu-unlock",
        "open-until-closed-latch"
      ],
      "clear_for_timed_open": true,
      "wireless_code_panel_describes": "paired-relays",
      "other_masks_in_same_byte": {
        "0x0F": "advertising-power-profile",
        "0x80": "encrypted-communication-layout"
      },
      "client_must_mask": true,
      "refreshed_on_state_change": true,
      "minimum_firmware_version": 115,
      "older_firmware_value": 0,
      "decoded_by_backend": false
    },
    "other_node_types_value": "000000",
    "freshness": {
      "source": "latest-bluetooth-advertisement",
      "age_field": "lastHeardFrom",
      "unchanged_reading_proves_online": false
    },
    "history": {
      "per_sensor_endpoint": "GET /api/temperature-control/history/{sensorId}",
      "aggregate_endpoint": "GET /api/temperature-control/stats",
      "interval_minutes": 5,
      "stored_fields": [
        "temperatureC",
        "averageTempC",
        "lowestTempC",
        "highestTempC",
        "sensorCount"
      ],
      "sensors_without_valid_reading": "excluded",
      "snapshot_written_when_no_valid_reading": false,
      "humidity_included": false
    },
    "risk": "read-only",
    "approval_required": false,
    "queue": false,
    "physical_operation": false
  },
  "tenant_gateway_wifi_policy": {
    "read_endpoint": "GET /api/tenants/gateway-wifi",
    "save_endpoint": "PUT /api/tenants/gateway-wifi",
    "forget_endpoint": "DELETE /api/tenants/gateway-wifi?ssid=<URL_ENCODED_SSID>",
    "operation_ids": [
      "getTenantGatewayWifiCredentials",
      "saveTenantGatewayWifiCredentials",
      "deleteTenantGatewayWifiCredentials"
    ],
    "schema": "GatewayWifiCredentials",
    "authentication": "bearer-plus-auth-filter-tenant-context",
    "tenant_argument_allowed": false,
    "api_user_tenant_derived_when_header_omitted": true,
    "human_tenant_membership_required": true,
    "required_access": "unrestricted-empty-role-list",
    "restricted_role_access": "403-forbidden",
    "scope": "multiple-networks-per-tenant-one-entry-per-exact-ssid",
    "request": {
      "ssid": "required-string-1-to-32-utf8-bytes-preserved-exactly",
      "password": "required-string-0-to-64-utf8-bytes-empty-for-open-network-preserved-exactly"
    },
    "read_response": {
      "saved": "200-array-of-ssid-and-unmasked-password-entries",
      "absent": "200-empty-array",
      "order": "ssid-case-sensitive-string-order"
    },
    "save_response": "204-no-body-entry-persisted",
    "forget_response": "204-no-body-including-ssid-already-absent",
    "errors": {
      "400": "invalid-input-or-missing-tenant-context-or-missing-delete-ssid",
      "401": "missing-or-invalid-authentication-or-api-token-tenant-mismatch",
      "403": "role-denied-or-tenant-membership-denied",
      "404": "tenant-not-found"
    },
    "save_precondition": "client-confirms-successful-gateway-wifi-connection-and-user-authorizes-saving",
    "automatic_capture_from_gateway": false,
    "backend_connectivity_verification": false,
    "storage": "separate-tenant-settings-documents-excluded-from-ordinary-tenant-responses-and-updates",
    "update_semantics": "upsert-one-exact-ssid-preserve-other-networks-last-storage-write-per-ssid-wins-no-conditional-write",
    "tenant_cleanup_removes_saved_network": true,
    "forget_affects_existing_gateways": false,
    "success_cache_control": "no-store",
    "log_or_expose_credentials": false,
    "risk": "security-sensitive",
    "approval_required": true,
    "idempotent": true,
    "retry_policy": "reads-retryable-mutations-read-before-retry-and-do-not-overwrite-newer-intent",
    "verification": [
      "GET after save and privately compare the intended SSID entry",
      "GET after forget and confirm the exact SSID is absent"
    ],
    "queue": false,
    "events": false,
    "physical_operation": false,
    "http_success_confirms_connectivity": false,
    "request_body_shape": "single-GatewayWifiCredentials-entry-per-PUT",
    "network_identity": "exact-ssid-case-and-whitespace-sensitive",
    "forget_request": {
      "ssid": "required-query-parameter-1-to-32-utf8-bytes-url-encoded",
      "missing_ssid": "400-no-networks-deleted",
      "body": false,
      "other_networks_affected": false
    },
    "legacy_single_network_credentials": "included-in-list-updateable-and-deletable-by-ssid"
  },
  "email_branding_policy": {
    "endpoints": {
      "read": "GET /api/email-branding",
      "save": "PUT /api/email-branding"
    },
    "authentication": "bearer-plus-global-auth-filter-tenant-context",
    "allowed_access": [
      "unrestricted-empty-roles",
      "Restricted"
    ],
    "no_tenant_endpoint_argument": true,
    "schema": "EmailBrandingSettings",
    "allowed_templates": [
      "classic",
      "modern",
      "minimal",
      "elegant"
    ],
    "default_layout": "classic",
    "modern_colors": {
      "format": "six-digit-hex-with-leading-hash",
      "primaryColor": {
        "default": "#08788C",
        "usage": "header-and-accent"
      },
      "secondaryColor": {
        "default": "#001838",
        "usage": "outer-background-and-main-text"
      },
      "read_prefills_defaults": true,
      "header_text_contrast": "automatic",
      "other_templates": "ignored"
    },
    "logo": {
      "field": "logoBase64",
      "format": "data:image/png;base64,... or data:image/jpeg;base64,...",
      "max_decoded_bytes": 524288,
      "max_dimension_pixels": 2048,
      "read_returns_data_uri": true,
      "outgoing_delivery": "cid-inline-image-in-multipart-related",
      "precedence": [
        "valid-upload",
        "logoUrl"
      ],
      "invalid_legacy_image": "ignored-at-send"
    },
    "update_semantics": {
      "existing_text_and_url_fields": "replacement-omitted-null-blank-clears",
      "template": "omitted-null-preserves-blank-resets-classic",
      "primaryColor": "omitted-null-preserves-blank-resets-default",
      "secondaryColor": "omitted-null-preserves-blank-resets-default",
      "logoBase64": "omitted-null-preserves-blank-removes",
      "urls": "absolute-http-or-https-without-credentials",
      "ownership": "server-managed-authenticated-tenant"
    },
    "preview": "browser-sample-using-unsaved-values-no-email-sent-client-rendering-may-differ",
    "risk": "reversible-tenant-wide-presentation",
    "approval": "authorized-branding-change-no-additional-physical-approval",
    "idempotent": true,
    "retry": "GET-safe-PUT-read-before-retry-after-ambiguous-result-last-write-wins",
    "verification": [
      "GET /api/email-branding and compare persisted values",
      "separately-authorized-email-send-to-verify-inbox-rendering"
    ],
    "success_status": 200,
    "errors": {
      "400": "invalid-input-or-missing-tenant",
      "401": "invalid-authentication-or-tenant-mismatch",
      "403": "role-or-tenant-denied"
    },
    "queue": false,
    "events": false,
    "save_sends_email": false,
    "physical_operation": false,
    "changes_smtp_sender": false
  },
  "default_email_sender_policy": {
    "tenant_configuration_endpoint": "PUT /api/tenants",
    "tenant_read_endpoint": "GET /api/tenants",
    "tenant_context_source": "authenticated-tenant-context",
    "tenant_request_field": "defaultFromName",
    "stored_tenant_field": "defaultFromName",
    "default": "Your hotel <no.reply@solvotix.org>",
    "format": "display-name-angle-address",
    "applies_when": "tenant-specific SMTP is incomplete and the global mail server is used",
    "tenant_smtp_precedence": {
      "required_fields": [
        "smtpHost",
        "smtpUsername",
        "smtpPassword"
      ],
      "from_field": "smtpFrom"
    },
    "tenant_smtp_timeout_fallback": {
      "scope": [
        "backend-administrator-invitations",
        "backend-booking-email"
      ],
      "tenant_socket_timeout_ms": 60000,
      "timeout_is_total_request_deadline": false,
      "trigger": "socket-timeout-unless-delivery-already-reported",
      "fallback_attempts": 1,
      "transport": "application-configured-global-mail-sender",
      "from": "application-mail.from",
      "reply_to": "original-from",
      "preserves": [
        "recipients",
        "subject",
        "body",
        "branding"
      ],
      "non_timeout_errors": "propagate-without-fallback",
      "fallback_failure": "propagate-with-original-failure-suppressed",
      "recursive_fallback": false,
      "duplicate_delivery_possible": true,
      "inbox_delivery_guaranteed": false
    },
    "sender_domain_must_be_authorized_by_active_provider": true,
    "queue": false,
    "physical_operation": false,
    "risk": "configuration-changing",
    "approval_required": true,
    "idempotent": false,
    "automatic_retry": "forbidden-after-ambiguous-response",
    "verification": [
      "GET /api/tenants and confirm defaultFromName",
      "send one test email and inspect its From header"
    ]
  },
  "smart_lock_sound_configuration_policy": {
    "tenant_configuration_endpoint": "PUT /api/tenants",
    "tenant_read_endpoint": "GET /api/tenants",
    "tenant_context_source": "authenticated-tenant-context",
    "tenant_request_field": "soundLevel",
    "allowed_values": [
      "off",
      "low",
      "medium",
      "high"
    ],
    "default": "low",
    "legacy_field": "soundEnabled",
    "legacy_mapping": {
      "false": "off",
      "true": "low"
    },
    "stored_tenant_field": "soundLevel",
    "time_setting": {
      "payload_format_version": 4,
      "payload_offset": 12,
      "device_boot_request_value": true,
      "tenant_save_broadcast_value": false,
      "false_behavior": "apply-tenant-configuration-without-updating-node-time",
      "legacy_behavior": "payload-versions-before-2-update-time"
    },
    "nfc_reader": {
      "configuration_endpoint": "PUT /api/tenants",
      "verification_endpoint": "GET /api/tenants",
      "tenant_request_field": "nfcEnabled",
      "stored_tenant_field": "nfcEnabled",
      "supported_node_types": [
        10
      ],
      "payload_offset": 13,
      "false_wire_value": 0,
      "true_wire_value": 1,
      "missing_or_invalid_wire_value": 0,
      "default": false,
      "device_specific_configuration_supported": false,
      "delivery": "queue-set-time-version-4-for-every-tenant-device-on-effective-change",
      "success_proves_physical_application": false,
      "physical_operation": true,
      "device_reported_state": "action-26-status-format-version-2-offset-1-stored-as-reportedNfcEnabled"
    },
    "system_menu": {
      "tenant_request_field": "systemCode",
      "stored_tenant_field": "systemCode",
      "format": "exactly-six-decimal-digits",
      "missing_or_invalid_wire_value": "six-zero-bytes",
      "supported_node_types": [
        7,
        8,
        9,
        10
      ],
      "entry_sequence": "#<systemCode>#",
      "exit_key": "*",
      "active_indicator": "repeating-led-blink-until-exit-or-timeout",
      "options": {
        "1": "unlock",
        "2": "lock",
        "3": "erase-codes-and-clear-advertising-profile",
        "4": "restart-device",
        "5": "cycle-node-10-sound-level",
        "6": "physical-security-reset-and-access-mode-reset-to-standard",
        "8": "cycle-access-mode-standard-open-until-closed-forced-closed"
      },
      "sensitive": true,
      "node_type_8_options_act_on_paired_relays": true
    },
    "delivery": {
      "on_device_boot_request": "queue-versioned-configuration-and-update-time-for-requesting-device",
      "on_tenant_save": "queue-versioned-configuration-without-time-update-for-every-tenant-device-only-when-effective-sound-system-code-nfc-or-access-mode-setting-changes",
      "tenant_save_change_comparison": "normalized-wire-values",
      "unrelated_tenant_change": "no-device-message",
      "pending_set_time_conflict": "replace-with-newest-tenant-save-configuration",
      "success_proves_physical_application": false
    },
    "approval_required": true,
    "automatic_retry": "forbidden-after-ambiguous-response",
    "verification": [
      "device-queue",
      "delivery-or-acknowledgement",
      "physical-keypad-sound",
      "physical-code-test-after-an-access-mode-change"
    ],
    "access_mode": {
      "configuration_endpoint": "PUT /api/smartlocks/configuration/access-mode",
      "verification_endpoint": "GET /api/smartlocks/configuration/access-mode",
      "tenant_configuration_endpoint": "PUT /api/tenants",
      "tenant_request_field": "accessMode",
      "stored_tenant_field": "accessMode",
      "scope": "tenant-wide",
      "supported_node_types": [
        7,
        8,
        9,
        10
      ],
      "allowed_values": [
        "standard",
        "openUntilClosed",
        "forcedClosed"
      ],
      "default": "standard",
      "payload_offset": 14,
      "wire_values": {
        "standard": 1,
        "openUntilClosed": 2,
        "forcedClosed": 3
      },
      "unchanged_wire_value": 0,
      "missing_or_invalid_wire_value": 1,
      "behavior": {
        "standard": "valid-code-opens-and-device-closes-again-on-its-own",
        "openUntilClosed": "valid-code-keeps-lock-open-until-star-key-close-command-or-system-menu-lock",
        "forcedClosed": "local-codes-and-cards-refused-and-reported-invalid-api-and-system-menu-still-open"
      },
      "device_specific_configuration_supported": false,
      "invalid_value_status": 400,
      "missing_tenant_status": 400,
      "tenant_not_found_status": 404,
      "delivery": "queue-set-time-version-4-for-every-tenant-device-on-effective-change",
      "local_menu_override": "system-menu-option-8-changes-and-persists-the-mode-on-a-single-device",
      "device_reported_state": {
        "source": "action-26-time-request-status-format-version-2",
        "status_offset": 2,
        "stored_sensor_fields": [
          "reportedAccessMode",
          "reportedNfcEnabled",
          "reportedStatusAt"
        ],
        "verification_endpoint": "GET /api/sensors/{sensorId}"
      },
      "idempotent": true,
      "approval_required": true,
      "automatic_retry": "forbidden-after-ambiguous-response",
      "success_proves_physical_application": false,
      "physical_operation": true,
      "held_open_devices_ignore_credentials": "valid-code-or-card-never-closes-a-device-held-open-by-open-command-system-menu-unlock-or-open-until-closed-latch",
      "timed_openings_unaffected": [
        "pulse-open",
        "standard-grant"
      ]
    }
  },
  "tenant_profile_policy": {
    "tenant_configuration_endpoint": "PUT /api/tenants",
    "tenant_read_endpoint": "GET /api/tenants",
    "tenant_context_source": "authenticated-tenant-context",
    "tenant_request_field": "profile",
    "stored_tenant_field": "profile",
    "allowed_values": [
      "hotel",
      "office",
      "private",
      "storage",
      "camping",
      "agriculture",
      "undefined"
    ],
    "default": "undefined",
    "missing_or_unrecognized_value": "undefined",
    "purpose": "descriptive-tenant-metadata",
    "affects_device_behavior": false,
    "queue": false,
    "physical_operation": false,
    "update_semantics": "tenant-document-replaced-read-before-write",
    "risk": "configuration-changing",
    "approval_required": false,
    "verification": [
      "GET /api/tenants and confirm the stored profile"
    ]
  },
  "clean_room_automated_message_policy": {
    "configuration_endpoints": [
      "POST /api/automation/messages/triggers",
      "PUT /api/automation/messages/triggers/{id}"
    ],
    "verification_endpoint": "GET /api/automation/messages/triggers",
    "authentication": "bearer-plus-tenant-context",
    "request_field": "sendOnlyWhenRoomClean",
    "requires": "sendToBookingGuest=true",
    "default": false,
    "dirty_or_missing_room_behavior": "persist-deferred-without-successful-delivery-log-unless-booking-is-checked-in",
    "release_condition": "booking-checked-in-or-assigned-room-clean-and-booking-match",
    "reevaluation": "approximately-every-minute",
    "expiry": {
      "on_day_of_arrival": "tenant-local-next-midnight",
      "on_day_of_departure": "tenant-local-next-midnight",
      "on_booking_created": "booking-start",
      "when_start_time_has_passed": "booking-end",
      "on_check_in": "booking-end",
      "on_checkout": "checkout-plus-48-hours"
    },
    "risk_class": "reversible-guest-communication-policy",
    "approval_required": true,
    "post_retry": "forbidden-after-ambiguous-response",
    "put_retry": "verify-current-trigger-before-retry",
    "booking_block_reason_field": {
      "field": "automatedMessageBlockReason",
      "type": "integer",
      "values": {
        "0": "ALL_OK",
        "1": "ROOM_NOT_CLEAN",
        "2": "NOT_PAID",
        "3": "NO_RECIPIENT_CHANNEL",
        "4": "DISPATCH_FAILED",
        "5": "ROOM_NOT_INCLUDED"
      },
      "read_endpoint": "GET /api/bookings",
      "client_writable": false,
      "multiple_block_precedence": "ROOM_NOT_CLEAN-before-NOT_PAID",
      "successful_delivery_precedence": "messageSent=true-returns-ALL_OK-even-after-an-earlier-failure",
      "current_cleaning_preview": "an-unsent-unchecked-in-booking-in-the-current-dirty-cleaning-room-list-returns-ROOM_NOT_CLEAN-before-when-start-time-has-passed-only-if-cleaning-module-and-updateCheckInTimeOnClean-are-enabled-and-earliest-access-time-has-passed",
      "deliverable_channel_completion": "configured-channels-without-corresponding-booking-contact-details-are-not-pending-after-all-deliverable-channels-succeed"
    },
    "delivery_verification": "GET /api/bookings exposes messageSent and automatedMessageBlockReason; per-channel logs are available from the booking logs endpoint",
    "physical_operation": false
  },
  "paid_or_checked_in_automated_message_policy": {
    "configuration_endpoints": [
      "POST /api/automation/messages/triggers",
      "PUT /api/automation/messages/triggers/{id}"
    ],
    "verification_endpoint": "GET /api/automation/messages/triggers",
    "authentication": "bearer-plus-tenant-context",
    "request_field": "onlySendIfPaidOrCheckedIn",
    "requires": "sendToBookingGuest=true",
    "default": false,
    "unsettled_booking_behavior": "persist-deferred-without-successful-delivery-log",
    "release_condition": "booking-paid-in-full-within-tolerance-or-checked-in",
    "settled_definition": "totalAmount-above-zero-and-amountPaid-at-least-totalAmount-minus-2",
    "mews_payment_import": "reservation-linked charged payments first; when insufficient, account-level charged payments are correlated by bill only if every bill order item belongs to one reservation; order items on closed bills are treated as paid while open bills remain unpaid",
    "unpriced_booking_treatment": "absent-or-zero-total-is-not-settled",
    "combines_with": "sendOnlyWhenRoomClean-requires-both-for-unchecked-in-bookings;check-in-overrides-clean-room-gate",
    "reevaluation": "approximately-every-minute-and-on-booking-update",
    "expiry": {
      "on_day_of_arrival": "tenant-local-next-midnight",
      "on_day_of_departure": "tenant-local-next-midnight",
      "on_booking_created": "booking-start",
      "when_start_time_has_passed": "booking-end",
      "on_check_in": "booking-end",
      "on_checkout": "checkout-plus-48-hours"
    },
    "risk_class": "reversible-guest-communication-policy",
    "approval_required": true,
    "post_retry": "forbidden-after-ambiguous-response",
    "put_retry": "verify-current-trigger-before-retry",
    "booking_block_reason_field": {
      "field": "automatedMessageBlockReason",
      "type": "integer",
      "values": {
        "0": "ALL_OK",
        "1": "ROOM_NOT_CLEAN",
        "2": "NOT_PAID",
        "3": "NO_RECIPIENT_CHANNEL",
        "4": "DISPATCH_FAILED",
        "5": "ROOM_NOT_INCLUDED"
      },
      "read_endpoint": "GET /api/bookings",
      "client_writable": false,
      "multiple_block_precedence": "ROOM_NOT_CLEAN-before-NOT_PAID",
      "successful_delivery_precedence": "messageSent=true-returns-ALL_OK-even-after-an-earlier-failure",
      "current_cleaning_preview": "an-unsent-unchecked-in-booking-in-the-current-dirty-cleaning-room-list-returns-ROOM_NOT_CLEAN-before-when-start-time-has-passed-only-if-cleaning-module-and-updateCheckInTimeOnClean-are-enabled-and-earliest-access-time-has-passed",
      "deliverable_channel_completion": "configured-channels-without-corresponding-booking-contact-details-are-not-pending-after-all-deliverable-channels-succeed"
    },
    "delivery_verification": "GET /api/bookings exposes messageSent and automatedMessageBlockReason; per-channel logs are available from the booking logs endpoint",
    "physical_operation": false
  },
  "room_code_generation_settings_policy": {
    "endpoint": "PUT /api/bookings/rooms/code-generation-settings",
    "authentication": "bearer-plus-tenant-context",
    "required_role": "Receptionist",
    "request_fields": {
      "roomIds": "non-empty-list-of-room-ids-in-current-tenant",
      "excludedDigits": "distinct-string-digits-zero-through-nine-with-at-least-two-digits-remaining"
    },
    "scope": "automatic-generation-and-automatic-selection-for-the-listed-rooms",
    "unused_conflicting_codes": "removed-from-room-and-queued-for-removal-from-code-capable-room-locks",
    "replacement_behavior": "one-compliant-unused-code-created-for-each-unused-code-removed-and-queued-to-code-capable-room-locks",
    "active_conflicting_codes": "retained-until-booking-release-then-removed-and-replaced",
    "manual_assignment": "explicit-manual-code-assignment-is-not-random-generation",
    "idempotent": true,
    "automatic_retry": "verify-with-GET-/api/bookings/rooms-before-retry-after-ambiguous-response",
    "approval_required": true,
    "risk_class": "physical-access-credential-policy-change",
    "physical_operation": true,
    "physical_completion_rule": "response-confirms-persistence-and-command-queueing-not-lock-delivery",
    "verification": "GET /api/bookings/rooms then GET /api/bookings/rooms/{roomId}/codes/health for-each-updated-room"
  },
  "tenant_room_code_length_policy": {
    "configuration_endpoint": "PUT /api/tenants",
    "read_endpoint": "GET /api/tenants",
    "tenant_request_field": "roomCodeLength",
    "allowed_integer_range": [
      4,
      7
    ],
    "default": 4,
    "scope": "newly-generated-and-automatically-selected-room-codes-including-booking-assignment-pool-replenishment-refresh-and-policy-replacement",
    "existing_codes_changed": false,
    "existing_codes_of_other_length": "retained-but-not-automatically-selected-or-counted-toward-preloaded-pool",
    "tenant_save_queues_lock_commands": false,
    "lock_constraint": "new-code-length-must-match-existing-code-slot-length-on-each-lock",
    "invalid_value_status": 400,
    "risk_class": "physical-access-credential-policy-change",
    "approval_required": true,
    "automatic_retry": "read-current-tenant-before-retrying-ambiguous-save",
    "verification": "GET /api/tenants then GET /api/bookings/rooms/{roomId}/codes/health-after-code-generation"
  },
  "room_code_health_policy": {
    "endpoint": "GET /api/bookings/rooms/{roomId}/codes/health",
    "authentication": "bearer-plus-tenant-context",
    "required_role": "Receptionist",
    "read_only": true,
    "idempotent": true,
    "automatic_retry": "allowed",
    "approval_required": false,
    "sensitive_fields": [
      "code",
      "takenByBookingId"
    ],
    "uploaded_definition": "slot-state-ADDED_TO_LOCK-and-uploadedToLockAt-present",
    "code_statuses": [
      "UPLOADED",
      "MISSING",
      "PENDING_UPLOAD",
      "PENDING_REMOVAL",
      "PENDING_CONFIRMATION",
      "UNKNOWN_STATE"
    ],
    "room_statuses": [
      "HEALTHY",
      "DEGRADED",
      "NO_CODES",
      "NO_CODE_CAPABLE_LOCKS"
    ],
    "non_code_capable_sensors": "excluded",
    "unresolved_assigned_sensors": "reported-and-prevent-healthy-status",
    "side_effects": "none-no-refresh-no-queue-no-resync",
    "verification": "repeat-same-endpoint-after-separately-approved-remediation",
    "physical_completion_rule": "pending-or-queued-is-not-complete"
  },
  "lock_user_numeric_code_upload_policy": {
    "read_endpoints": [
      "GET /api/lock-users",
      "GET /api/lock-users/{id}"
    ],
    "compatibility_alias": "/api/lockusers",
    "authentication": "existing-bearer-and-auth-filter-tenant-context",
    "tenant_argument_allowed": false,
    "roles": "existing-lock-user-access-policy",
    "read_only": true,
    "approval_required": false,
    "idempotent": true,
    "pending_pair_count_field": "codesNotUploadedToAllSensors",
    "distinct_pending_sensor_ids_field": "sensorIdsWithCodesNotUploaded",
    "scope": "assigned-code-capable-sensors-with-at-least-one-numeric-code-not-confirmed-uploaded",
    "uploaded_definition": "matching-slot-state-ADDED_TO_LOCK-and-uploadedToLockAt-present",
    "unsupported_or_unresolved_sensors": "excluded-as-in-existing-pair-count",
    "empty_result": "empty-array-when-no-numeric-codes-or-no-pending-pairs",
    "computed_before_credential_masking": true,
    "restricted_users_receive_sensor_ids": true,
    "client_writable": false,
    "persisted": false,
    "mifare_and_wallet_included": false,
    "verification": "read-lock-user-again-and-map-pending-sensor-IDs-to-tenant-inventory",
    "retry": "bounded-backoff-for-transient-reads-no-authentication-or-authorization-retry",
    "queue": false,
    "events": false,
    "physical_operation": false
  },
  "lock_user_mifare_credential_policy": {
    "endpoints": {
      "add_credential": "POST /api/lock-users/{lockUserId}/mifare-credentials",
      "remove_credential": "DELETE /api/lock-users/{lockUserId}/mifare-credentials/{mifareUid}",
      "set_numeric_codes": "PUT /api/lock-users/{lockUserId}"
    },
    "authentication": "bearer-plus-tenant-context",
    "risk": "security-sensitive",
    "approval_required": true,
    "request_fields": {
      "mifareUid": "hex-with-optional-separators-4-7-or-10-bytes-stored-uppercase",
      "code": "optional-4-to-7-digit-pin-matching-the-lock-existing-code-length"
    },
    "credential_types": {
      "uid_only": "mifare",
      "uid_plus_pin": "mifare_pin"
    },
    "supported_device_types": [
      "lock_8015",
      "lock_s42"
    ],
    "unsupported_assigned_sensors": "skipped-without-error",
    "slot_space": "shared-with-numeric-access-codes",
    "repeat_uid_behavior": "replaces-stored-pin-does-not-duplicate",
    "removal_scope": "queued-only-when-no-other-lock-user-still-grants-the-uid-on-that-lock",
    "delete_all_codes_erases_mifare_credentials": true,
    "response": "updated-lock-user-with-mifareCredentialsNotUploadedToAllSensors",
    "uploaded_definition": "slot-state-ADDED_TO_LOCK-and-uploadedToLockAt-present",
    "pending_upload_recovery": "same-five-minute-monitor-as-numeric-access-codes",
    "automatic_retry": "forbidden",
    "credential_logging": "forbidden",
    "verification": [
      "GET /api/lock-users/{lockUserId}",
      "GET /api/smartlocks/{lockId}/codes/slots",
      "GET /api/events action 1028 with data.credentialType mifare or mifare_pin"
    ],
    "confirms_physical_delivery": false
  },
  "wallet_certificate_policy": {
    "endpoints": {
      "list": "GET /api/wallet-certificates",
      "get": "GET /api/wallet-certificates/{id}",
      "create": "POST /api/wallet-certificates",
      "update": "PUT /api/wallet-certificates/{id}",
      "delete": "DELETE /api/wallet-certificates/{id}",
      "generate_install_package": "POST /api/wallet-certificates/{id}/package",
      "assign_to_lock_user": "POST /api/lock-users/{lockUserId}/wallet-certificates",
      "remove_from_lock_user": "DELETE /api/lock-users/{lockUserId}/wallet-certificates/{walletCertificateId}",
      "assign_to_room": "POST /api/bookings/rooms/{roomId}/wallet-certificates",
      "list_for_room": "GET /api/bookings/rooms/{roomId}/wallet-certificates",
      "remove_from_room": "DELETE /api/bookings/rooms/{roomId}/wallet-certificates/{walletCertificateId}"
    },
    "authentication": "bearer-plus-tenant-context",
    "tenant_argument_accepted": false,
    "platforms": [
      "APPLE",
      "ANDROID"
    ],
    "defaults": {
      "companyName": "Your company",
      "logoUrl": "https://solvotix.net/images/solvotix-wide-logo.png"
    },
    "secret_material_in_api": false,
    "apple_response": "application/vnd.apple.pkpass-signed-package",
    "android_response": "json-with-short-lived-saveUrl-and-expiresAt",
    "risk": "security-sensitive-digital-card-issuance",
    "approval_required": true,
    "package_generation_physical_operation": false,
    "assignment_physical_operation": true,
    "credential_id": "read-only-32-character-uppercase-hex-presented-by-phone-and-stored-on-lock",
    "supported_device_types": [
      "lock_8015",
      "lock_s42"
    ],
    "unsupported_assigned_sensors": "skipped-without-error",
    "assignment_storage": {
      "lock_user": "LockUser.walletCertificateIds",
      "room": "RoomWalletCertificates.walletCertificateIds"
    },
    "shared_sensor_removal": "remove-from-lock-only-when-no-other-room-or-lock-user-still-grants-certificate",
    "sensor_change_sync": true,
    "persisted_assignment_reconciliation": "every-five-minutes-idempotent-and-does-not-prove-delivery",
    "delete_certificate_removes_assignments_and_queues_lock_removal": true,
    "package_generation_retry": "allowed-on-503-with-bounded-backoff",
    "mutation_automatic_retry": "forbidden",
    "inactive_or_expired_status": 409,
    "signing_or-logo-unavailable_status": 503,
    "verification": [
      "GET /api/wallet-certificates/{id} verifies stored metadata only",
      "successful generation does not prove phone installation",
      "verify installation in the phone wallet UI",
      "GET /api/smartlocks/{lockId}/codes/slots verifies lock upload state",
      "GET /api/events action 1028 or 1029 with wallet credential type verifies delivery processing"
    ],
    "certificate_creation_authorizes_lock_access": false,
    "assignment_authorizes_lock_access_when-uploaded": true,
    "assignment_response_confirms_physical_delivery": false,
    "confirms_phone_installation": false
  },
  "lock_automation_policy": {
    "endpoints": {
      "list_triggers": "GET /api/automation/locks/triggers/config",
      "list_tasks": "GET /api/automation/locks/tasks",
      "create_task": "POST /api/automation/locks/tasks",
      "update_task": "PUT /api/automation/locks/tasks/{taskId}",
      "delete_task": "DELETE /api/automation/locks/tasks/{taskId}",
      "run_now": "POST /api/automation/locks/tasks/{taskId}/run"
    },
    "authentication": "solvotix-api-user-bearer",
    "tenant_header_required": true,
    "required_role": "superuser",
    "module_gate": {
      "module_key": "automation_lock",
      "settings_endpoint": "GET /api/modules/settings",
      "when_disabled": "tasks-remain-manageable-but-never-execute-scheduled-or-manual"
    },
    "supported_triggers": [
      "open",
      "close",
      "pulse_open"
    ],
    "supported_device_types": [
      "lock_8015",
      "lock_s42",
      "lock_wireless_code_panel",
      "lock_controller",
      "relay",
      "high_voltage_relay"
    ],
    "trigger_effect": {
      "open": "lock-unlocks-and-stays-open; relay-closes-circuit-until-close-runs",
      "close": "lock-locks; relay-opens-circuit",
      "pulse_open": "lock-short-open-pulse; relay-pulses-for-configured-relay_open_ms"
    },
    "schedule": {
      "frequencies": [
        "ONCE",
        "DAILY",
        "WEEKLY",
        "MONTHLY"
      ],
      "interval_counted_from": "startDate",
      "byWeekdays_required_for": "WEEKLY",
      "byMonthDays_required_for": "MONTHLY",
      "nonexistent_month_day": "skipped-for-that-month",
      "time_of_day_format": "HH:mm",
      "date_format": "YYYY-MM-DD",
      "time_zone_default": "tenant-time-zone",
      "evaluated_in": "local-time-stable-across-daylight-saving",
      "triggers_per_task": 1
    },
    "execution": {
      "poll_interval_seconds": 60,
      "scheduled_time_precision": "approximately-one-minute",
      "occurrence_delivery": "at-most-once",
      "executed_marker_fields": [
        "lastFiredOccurrence",
        "lastFiredAt"
      ],
      "missed_occurrence_behavior": "skipped-not-replayed-outside-catch-up-window",
      "catch_up_window_setting": "lock.automation.catch-up-window-minutes",
      "catch_up_window_default_minutes": 10,
      "per_device_dispatch": "independent-one-failure-does-not-stop-others",
      "manual_run": "configured-trigger-queued-immediately-for-each-device-when-task-and-module-enabled",
      "manual_run_updates_lastFiredAt_to_requestedAt": true,
      "manual_run_changes_lastFiredOccurrence": false,
      "manual_run_occurrence": "manual:<runId>-in-per-device-events",
      "manual_run_can_overlap_scheduled_occurrence": true,
      "delete_recalls_queued_commands": false
    },
    "risk_class": "operationally_dangerous",
    "approval_required": true,
    "idempotent": {
      "create": false,
      "update": true,
      "delete": true,
      "run_now": false
    },
    "automatic_retry": {
      "create": "forbidden-after-ambiguous-response",
      "update": "allowed-after-re-reading-task",
      "delete": "allowed",
      "run_now": "forbidden-after-ambiguous-response"
    },
    "update_semantics": "full-replacement-preserves-userId-createdDate-and-fired-marker",
    "verification": [
      "GET /api/automation/locks/tasks",
      "GET /api/modules/settings",
      "GET /api/events for the executed or failed operation per device",
      "manual run: correlate each device event using occurrence manual:<runId> and verify physical state"
    ],
    "physical_operation": true,
    "queued_is_physical_completion": false
  },
  "api_surfaces": {
    "runner_machine_api": {
      "base_url": "https://backend.solvotix.org",
      "openapi": "https://backend.solvotix.org/v3/api-docs",
      "authentication": [
        "solvotix-api-user-bearer",
        "firebase-id-token"
      ],
      "tenant_scoped": true
    },
    "browser_session": {
      "base_path": "/api/auth/session",
      "credential": "firebase-id-token-to-http-only-cookie",
      "api_user_cookie_exchange_supported": false
    },
    "guest_portal": {
      "base_path": "/api/guest-portal",
      "authentication": "booking-scoped-guest-workflow",
      "bearer_tenant_header_is_not_booking_authorization": true,
      "access_window": {
        "method": "GET",
        "path": "/api/guest-portal/bookings/{bookingId}/validity",
        "operation_id": "getBookingValidity",
        "tenant_context": "existing-tenantId-query-parameter-with-booking-scoped-guest-workflow",
        "authentication": "booking-scoped-guest-workflow; no-bearer-token",
        "request_body": null,
        "statuses": {
          "0": "upcoming",
          "1": "access-allowed",
          "2": "checked-out-expired-or-missing-dates"
        },
        "response_times": {
          "checkoutTime": "stored-scheduled-departure-without-grace-extension",
          "date": "status-0-opening; status-1-effective-access-cutoff; time-expired-status-2-effective-access-cutoff; checked-out-or-missing-dates-null",
          "legacy_active_date": "null-client-falls-back-to-checkoutTime"
        },
        "grace_filter": "room_code_deactivation_grace_days",
        "grace_enabled_by": "filter-presence-in-tenant-persisted-booking-filters",
        "grace_days": "last-valid-nonnegative-number-or-integer-string-in-createdDate-order; default-zero",
        "grace_cutoff": "stored-end-plus-configured-elapsed-24-hour-days; denied-at-cutoff",
        "checked_out": "deny-immediately-even-inside-grace-independent-of-showCheckoutButton",
        "guest_reported_checkout": "access-cutoff-is-stored-five-minute-end; grace-days-do-not-extend-it",
        "canCancelCheckout": "true-only-for-pending-reported-future-deadline-with-saved-original-end",
        "checked_in_before_start": "with-grace-and-complete-dates-follow-lock-retention-policy-while-cutoff-not-reached",
        "missing_dates": "deny-guest-access",
        "without_filter": "original-inclusive-start-end-window",
        "zero_day_filter": "exclusive-end-boundary",
        "guard_scope": "room-code-and-room-reads-sensors-actions-messages-offers-directions-guest-AI-checkout",
        "other_gates": "existing-feature-toggles-room-device-membership-languages-and-modules-preserved",
        "limitToValidTime": "frontend-screen-policy-only-never-bypasses-backend-guards",
        "countdown": "stored-checkoutTime-without-grace; translated-checkout-time-has-passed-message-replaces-negative-countdown-after-departure; explicit-report-replaces-it-with-five-minute-deadline; recheck-validity-at-effective-access-cutoff",
        "checkout_button_during_grace": "on-and-after-tenant-local-departure-day-when-enabled-and-access-allowed",
        "metadata_and_contacts": "existing-outside-window-availability-preserved",
        "success": "200-current-policy-eligibility-not-physical-lock-state",
        "unknown_booking": "404",
        "guard_denial": "403",
        "risk": "low-read-only",
        "approval": "not-required-for-validity-read; explicit-guest-intent-for-physical-actions-and-checkout",
        "idempotent": true,
        "retry": "validity-read-safe-after-transient-failure; never-auto-retry-ambiguous-physical-action-or-checkout",
        "verification": "validity-200-response-for-policy; existing-queue-events-device-state-for-physical-command-delivery",
        "queue": false,
        "event": false,
        "physical_operation": false,
        "delayed_lock_removal_extends_access": false
      },
      "tenant_name": {
        "method": "GET",
        "path": "/api/guest-portal/bookings/{bookingId}/tenantName",
        "operation_id": "getGuestPortalTenantName",
        "authentication": "public-at-filter-layer; existing-booking-in-current-tenant-required",
        "tenant_context": "Tenant-header; legacy-tenantId-query-fallback; header-takes-precedence; resolved-by-authentication-filter",
        "returns": {
          "tenantName": "stored tenant display name only"
        },
        "availability": "before-during-and-after-stay-including-checkout; independent-of-display-settings",
        "risk": "low",
        "approval": "not-required",
        "read_only": true,
        "idempotent": true,
        "retry_policy": "safe-after-transient-failure; correct-context-or-booking-before-retrying-400-or-404",
        "verification": "read-tenantName-from-200-response; no-queue-or-event",
        "errors": {
          "400": "missing-tenant-context",
          "404": "unknown-booking-or-tenant-or-missing-or-blank-tenant-name"
        }
      },
      "timezone": {
        "method": "GET",
        "path": "/api/guest-portal/bookings/{bookingId}/timezone",
        "operation_id": "getGuestPortalTimezone",
        "authentication": "public-at-filter-layer; existing-booking-in-current-tenant-required",
        "tenant_context": "Tenant-header; legacy-tenantId-query-fallback; header-takes-precedence; resolved-by-authentication-filter",
        "returns": {
          "timezone": "stored tenant timezone only; no normalization or UTC fallback"
        },
        "availability": "before-during-and-after-stay-including-checkout; independent-of-display-settings",
        "risk": "low",
        "approval": "not-required",
        "read_only": true,
        "idempotent": true,
        "retry_policy": "safe-after-transient-failure; correct-context-or-booking-before-retrying-400-or-404",
        "verification": "read-timezone-from-200-response; no-queue-or-event",
        "errors": {
          "400": "missing-tenant-context",
          "404": "unknown-booking-or-tenant-or-missing-or-blank-tenant-timezone"
        }
      },
      "display_settings": {
        "method": "GET",
        "path": "/api/guest-portal/bookings/{bookingId}/display-settings",
        "tenant_context": "tenantId-query-parameter-with-booking-scoped-guest-workflow",
        "returns": "showRoom, showCode, showOpenButton, showCheckoutButton, limitToValidTime, askForContactDetailsConfirmation, showPreStayInstructions, preStayInstructions, contactDetailsConfirmed",
        "authentication": "booking-scoped-guest-workflow; no-bearer-token",
        "availability": "before-during-and-after-stay-including-checkout",
        "risk": "low",
        "approval": "not-required-for-read",
        "retry_policy": "idempotent; safe-after-transient-failure; correct-context-before-retrying-404",
        "verification": "200-response; cache-control-no-store; no-queue-or-event",
        "askForContactDetailsConfirmation": "tenant-toggle-enabled-and-contactDetailsConfirmed-false; independent-of-whether-phone-and-email-present; does-not-save-or-confirm",
        "showPreStayInstructions": "configured-tenant-toggle",
        "preStayInstructions": "selected-active-language-preStayMessages-message-or-preStayInstructions-default-only-under-existing-pre-stay-visibility-conditions; otherwise-null; plain-text-no-html-or-variable-expansion",
        "configuration": {
          "path": "/api/guest-portal-admin/settings",
          "methods": [
            "GET",
            "PUT"
          ],
          "authentication": "authenticated-tenant-session-with-Tenant-header",
          "write_policy": "tenant-approval-for-guest-visible-content-and-phone-collection; read-then-send-complete-settings-object",
          "defaults": {
            "askForContactDetailsConfirmation": false,
            "showPreStayInstructions": false,
            "preStayInstructions": ""
          },
          "update_semantics": "omitted-new-toggles-reset-false; null-text-clears; text-trimmed",
          "physical_access": "unchanged; no-early-access-granted"
        },
        "purpose": "guest-facing feature toggles; the authenticated /api/guest-portal-admin/settings endpoint must not be used by guest clients",
        "read_only": true,
        "unknown_booking": "404",
        "client_default_on_failure": "fail-closed; treat every show* toggle and askForContactDetailsConfirmation as false, hide instructions, and limitToValidTime as true",
        "pre_stay_languages": {
          "query_parameter": "language",
          "required": false,
          "precedence": [
            "matching-normalized-activated-language-entry",
            "preStayInstructions-default"
          ],
          "missing_blank_unsupported_inactive_or_untranslated_language": "use-default",
          "blank_default_without_override": "null",
          "response": "existing-preStayInstructions-field-only-no-translation-list",
          "selection_writes_settings": false,
          "configuration_field": "preStayMessages",
          "entry_fields": {
            "language": "required-supported-language",
            "message": "required-nonblank-plain-text-trimmed"
          },
          "normalization": "same-supported-catalogue-and-base-language-normalization-as-room-messages",
          "update_semantics": {
            "omitted_or_null": "preserve",
            "empty_array": "clear-all",
            "nonempty_array": "replace-entire-list"
          },
          "validation": "400-before-settings-write-for-null-entry-missing-or-unsupported-language-duplicate-normalized-language-or-null-blank-message",
          "legacy_admin_read": "empty-array-no-manual-migration-default-preserved",
          "saving_activates_language": false,
          "disabling_language_deletes_translation": false,
          "placeholders_expanded": false,
          "html_rendered": false,
          "visibility_gates_changed": false,
          "default_field_update": "existing-omitted-null-clears",
          "approval": "authorize-tenant-and-content-before-live-admin-save",
          "risk": "reversible-guest-visible-content",
          "retry": "read-before-retry-after-ambiguous-complete-settings-PUT",
          "verification": [
            "admin-settings-GET-compare-default-and-translations",
            "eligible-future-booking-display-settings-GET-with-each-language",
            "confirm-no-text-outside-pre-stay-conditions"
          ]
        }
      },
      "save_phone": {
        "method": "PUT",
        "path": "/api/guest-portal/bookings/{bookingId}/phone",
        "operation_id": "saveGuestPortalPhoneNumber",
        "authentication": "booking-scoped-guest-workflow; no-bearer-token",
        "tenant_context": "Tenant-header; filter-resolved; legacy-tenantId-query-fallback; header-precedence",
        "request": {
          "phone": "string; 7-15-digits; optional-leading-plus; strip-spaces-parentheses-dots-hyphens; max-64-input-characters"
        },
        "preconditions": [
          "booking-exists-in-tenant",
          "tenant-askForContactDetailsConfirmation-enabled",
          "phone-missing-or-blank; identical-normalized-existing-phone-is-no-op"
        ],
        "availability": "before-during-and-after-stay-including-checkout; independent-of-limitToValidTime",
        "risk": "moderate-personal-data-mutation",
        "approval": "explicit-guest-submission",
        "persistence": "conditional-missing-phone-write-on-unconfirmed-booking; does-not-confirm-contacts-or-protect-new-submissions-from-sync",
        "legacy_phone_migration": "none; existing-legacy-origin-markers-continue-to-protect-phone-only; new-phone-only-submissions-remain-unconfirmed",
        "confirmation_workflow": "use-GET-and-PUT-contact-details-for-explicit-phone-and-email-confirmation",
        "success": "204-no-body; saved-locally-or-same-normalized-phone-already-present",
        "errors": {
          "400": "missing-tenant-or-invalid-body-or-phone",
          "403": "contact-confirmation-prompt-disabled",
          "404": "unknown-booking",
          "409": "existing-different-phone-or-concurrent-conflict"
        },
        "retry_policy": "same-payload-safe-after-transient-failure; no-op-on-same-normalized-number; stop-on-409",
        "verification": "204-confirms-local-phone; phone-only-save-does-not-clear-contact-confirmation-prompt; use-contact-details-to-confirm",
        "event": {
          "action": 1034,
          "state": "updated",
          "actor": "guest",
          "payload": "existing-booking-metadata-including-phone-and-any-contact-room-code-date-fields; sensitive",
          "no_op_emits_event": false,
          "atomic_with_phone_write": false
        },
        "phone_ownership_verified": false,
        "provider_sync_guaranteed": false,
        "side_effects": "no-message-physical-command-or-provider-update-queued; existing-automation-may-use-stored-phone"
      },
      "contact_details": {
        "path": "/api/guest-portal/bookings/{bookingId}/contact-details",
        "methods": [
          "GET",
          "PUT"
        ],
        "operation_ids": {
          "GET": "getGuestPortalContactDetails",
          "PUT": "confirmGuestPortalContactDetails"
        },
        "authentication": "booking-scoped-guest-workflow; no-bearer-token",
        "tenant_context": "filter-resolved-Tenant-header; legacy-tenantId-query-fallback; header-precedence",
        "availability": "before-during-and-after-stay-including-checkout; independent-of-askForContactDetailsConfirmation-and-limitToValidTime",
        "read": {
          "success": "200; phone-email-contactDetailsConfirmed; contacts-may-be-null",
          "risk": "personal-data-read",
          "approval": "not-required",
          "cache": "no-store",
          "retry": "idempotent-safe-after-transient-failure",
          "side_effects": "no-queue-or-event"
        },
        "confirmation": {
          "request": {
            "phone": "required; 7-15-digits; optional-plus; strip-spaces-parentheses-dots-hyphens; max-64-raw-characters",
            "email": "required-single-valid-address; max-254-raw-characters; trim-outer-whitespace; retain-case; no-line-breaks-or-display-name",
            "contactDetailsConfirmed": "required-true"
          },
          "risk": "moderate-personal-data-mutation",
          "approval": "explicit-guest-review-and-confirmation-of-both-values; never-auto-confirm",
          "persistence": "atomic-phone-email-and-confirmation-write; conditional-on-contact-snapshot-and-not-yet-confirmed",
          "success": "204; saved-and-confirmed-or-identical-confirmed-contacts-already-present",
          "retry": "same-payload-safe; on-409-re-read-and-review; no-silent-replacement",
          "event": "1034; state=updated; guest-actor; normal-booking-metadata-including-contacts; no-op-emits-no-event; logging-separate-from-write",
          "ownership_verified": false,
          "provider_update_queued": false,
          "physical_operation": false
        },
        "sync_policy": "preserve-phone-and-email-when-existing-contactDetailsConfirmed-true; other-fields-sync-normally; legacy-phone-marker-protects-only-phone",
        "migration": "no-automatic-contact-confirmation-backfill",
        "concurrent_sync_limitation": "whole-booking-save-loaded-before-confirmation-can-overwrite-simultaneous-confirmation",
        "errors": {
          "400": "missing-tenant; PUT-also-invalid-contacts-or-confirmation-not-true",
          "404": "booking-not-found",
          "409": "PUT-confirmed-different-values-or-concurrent-conflict"
        },
        "verification": "GET-contact-details-check-both-values-and-confirmation; display-settings-also-exposes-contactDetailsConfirmed"
      },
      "checkout": {
        "method": "POST",
        "path": "/api/guest-portal/bookings/{bookingId}/checkout",
        "tenant_context": "tenantId-query-parameter-with-booking-scoped-guest-workflow",
        "approval": "explicit-guest-intent-required",
        "local_success_is_provider_completion": false,
        "success_status": 200,
        "success_meaning": "persisted-departure-report-not-completed-checkout",
        "reported_flag": "checkoutSyncRequestedByGuest=true-for-all-booking-sources",
        "checkout_delay_seconds": 300,
        "report_checkedOut": false,
        "report_checkedIn": "unchanged",
        "report_checkoutTime": "stored-end-five-minutes-after-request",
        "original_end_saved": "hidden-sync-protected-guestCheckoutPreviousEnd-in-same-booking-document",
        "roomMarkedDirty_on_report": false,
        "room_dirty_timing": "deferred-until-local-checkout-completion; durable-pending-flag-for-retry",
        "normal_grace_days_extend_reported_deadline": false,
        "local_completion": "monitor-only-when-guest-flag-true-and-stored-end-reached; conditional-update-matching-deadline",
        "normal_expiry_sets_checkedOut": false,
        "monitor_default_fixed_delay_ms": 60000,
        "local_completion_lag": "next-monitor-pass-after-deadline",
        "report_event": "1034-data.state-updated",
        "completion_event": "1034-data.state-checked_out",
        "event_persistence_atomic_with_booking": false,
        "provider_reconciliation": "after-local-completion; durable-retry-for-supported-provider-bookings-previously-checked-in",
        "repeated_pending_or_completed_report_status": 403,
        "repeated_report_extends_deadline": false,
        "expiry_filter_required": false,
        "guest_intent_persisted_separately": true,
        "inbound_snapshot_reopens_guest_checkout": false,
        "post_checkout_code_use_initiates_pms_checkin": false,
        "retry_policy": "do-not-repeat-after-local-success; monitor-retries-transient-provider-failures",
        "verification": [
          "200 checkedOut=false and checkoutTime confirm scheduled report",
          "GET booking validity confirms access deadline and later checkedOut state",
          "confirm checkout in source provider",
          "local checkedOut=true and data.state=checked_out alone do not prove provider completion"
        ],
        "staff_reopen": {
          "method": "PUT",
          "path": "/api/bookings/bookings/{bookingId}",
          "authentication": "authenticated-receptionist-with-tenant-context",
          "approval": "explicit-operator-intent",
          "trigger": "persisted-checkedOut=true-to-submitted-false",
          "clears": [
            "guest-departure-report-flag",
            "checkout-request-metadata",
            "provider-checkout-sync-status-attempts-timestamps-error",
            "guest-rollback-fields",
            "deferred-cleaning-marker"
          ],
          "submitted_end_and_checkedIn": "preserved-as-submitted; original-end-not-reconstructed",
          "room_cleaning_state": "unchanged",
          "pending_or_completed_provider_device_action": "not-undone-or-cancelled; in-flight-save-race-remains",
          "ordinary_edit_preserves_departure_cycle": true,
          "new_guest_report": "allowed-when-access-valid-and-checkout-enabled; fresh-five-minute-deadline",
          "normal_access_automation_provider_rules": "continue",
          "verification": [
            "GET /api/bookings/bookings",
            "GET booking-scoped guest validity"
          ],
          "event": "1034-data.state-updated; separate-from-booking-persistence",
          "ambiguous_mutation_retry": "verify-state-before-renewed-explicit-intent"
        }
      },
      "checkout_cancel": {
        "method": "POST",
        "path": "/api/guest-portal/bookings/{bookingId}/checkout/cancel",
        "operation_id": "cancelCheckout",
        "authentication": "booking-scoped-guest-workflow-no-bearer",
        "tenant_context": "required-nonblank-tenantId-query-parameter",
        "request_body": null,
        "approval": "explicit-guest-intent-required",
        "risk": "booking-and-access-restoration",
        "preconditions": [
          "checkoutSyncRequestedByGuest=true",
          "checkedOut=false",
          "reported-end-strictly-future",
          "original-end-saved"
        ],
        "visibility_toggle_required": false,
        "success_status": 200,
        "response_schema": "BookingValidityResponse",
        "effects": [
          "restore-exact-original-stored-end",
          "clear-guest-report-flag",
          "restore-previous-request-timestamp-and-requested-while-checked-in-marker",
          "remove-rollback-fields"
        ],
        "checkedIn_and_checkedOut": "unchanged",
        "cleaning_state": "unchanged-during-report-and-cancellation",
        "canCancelCheckout_after_success": false,
        "returns_physical_completion": false,
        "provider_or_device_command": false,
        "completed_provider_checkout_undone": false,
        "original_end_already_past": "restored-normal-policy-may-deny-access",
        "event": "1034-data.state-updated-guest-actor",
        "event_atomic_with_persistence": false,
        "errors": {
          "400": "missing-or-blank-tenant-context",
          "404": "unknown-booking",
          "409": "not-pending-expired-completed-missing-legacy-snapshot-or-concurrent-change"
        },
        "legacy_reports": "reject-without-original-end-do-not-infer",
        "concurrency": "conditional-update-matches-report-and-original-end; whole-booking-import-save-already-in-progress-not-serialized",
        "repeated_cancel_status": 409,
        "automatic_retry": false,
        "verification": [
          "GET-booking-validity-restored-checkoutTime",
          "canCancelCheckout=false",
          "physical-state-requires-existing-device-verification"
        ]
      },
      "room_messages": {
        "configuration_path": "/api/guest-portal-admin/settings",
        "shared_rooms_field": "messages[].roomIds",
        "all_language_default": "messages[].language omitted",
        "precedence": [
          "matching room and language",
          "matching room without language",
          "empty room instructions"
        ],
        "composition": "insert into independently selected general template only at {roominstructions}"
      },
      "general_messages": {
        "configuration_path": "/api/guest-portal-admin/settings",
        "configuration_methods": [
          "GET",
          "PUT"
        ],
        "authentication": "existing-authenticated-tenant-session-or-bearer-with-auth-filter-Tenant-context",
        "new_tenant_argument": false,
        "fallback_field": "generalMessageTemplate",
        "translations_field": "generalMessages",
        "entry_fields": {
          "language": "required-supported-language",
          "message": "required-nonblank-template-trimmed"
        },
        "normalization": "same-as-room-messages-trim-underscore-to-hyphen-base-language-lowercase",
        "update_semantics": {
          "omitted_or_null": "preserve-existing-translations",
          "empty_array": "clear-all-overrides",
          "nonempty_array": "replace-complete-list-omitted-entry-is-deleted",
          "other_settings": "existing-complete-settings-update-semantics"
        },
        "legacy_read": "empty-array-existing-default-preserved-no-manual-migration",
        "validation": "400-before-settings-write-for-null-entry-missing-or-unsupported-language-duplicate-normalized-language-or-null-blank-message",
        "precedence": [
          "matching-requested-language-override",
          "generalMessageTemplate",
          "existing-built-in-default-if-fallback-null-or-blank"
        ],
        "room_resolution": "independent-matching-room-language-then-room-default-then-empty-text",
        "composition": "existing-booking-variables-in-both-pieces-room-instructions-inserted-only-at-{roominstructions}",
        "booking_variables": [
          "{name}",
          "{room}",
          "{code}",
          "{departureDate}"
        ],
        "date_policy_changed": false,
        "activated_language_required": true,
        "saving_activates_language": false,
        "disabling_language_deletes_translation": false,
        "outgoing_automated_messages": "unchanged-use-raw-room-instructions-without-general-template",
        "pre_stay_instructions": "separate-preStayMessages-plain-text-translations-with-existing-visibility-rules",
        "guest_read": {
          "path": "/api/guest-portal/bookings/{bookingId}/messages",
          "query": [
            "tenantId",
            "language"
          ],
          "bearer_required": false,
          "preconditions": [
            "booking-in-tenant-with-room",
            "booking-window-allowed",
            "requested-language-activated"
          ],
          "response": "existing-GuestPortalMessage-normalized-requested-language-and-composed-message-no-translation-list",
          "errors": {
            "400": "missing-input",
            "403": "booking-window-disallowed",
            "404": "booking-unresolved-room-assignment-missing-or-language-unavailable"
          }
        },
        "success": "200-saved-settings-not-guest-delivery",
        "risk": "reversible-guest-visible-content",
        "approval": "authorized-tenant-and-content-before-live-save",
        "physical_operation": false,
        "outbound_communication": false,
        "new_events": false,
        "retry": "reads-repeatable-same-complete-PUT-idempotent-for-these-fields-read-before-retry-after-ambiguous-save",
        "verification": [
          "admin-GET-check-default-and-overrides",
          "eligible-booking-message-GET-for-each-activated-language"
        ],
        "sensitive_output": "do-not-log-rendered-messages-access-codes-or-booking-links"
      },
      "automated_message_templates": {
        "fields": [
          "roomMessages[].roomIds",
          "roomMessages[].language",
          "roomMessages[].message",
          "roomMessages[].smsMessage",
          "roomMessages[].emailMessage"
        ],
        "precedence": [
          "raw matching guest-portal room instruction",
          "matching automated roomMessages instruction",
          "empty roominstructions"
        ],
        "composition": "selected raw room instruction replaces {roominstructions} in the legacy general or channel-specific template; guest-portal general wrapper is excluded",
        "date_variables": {
          "numeric": "{departureDate}",
          "text": "{departureDateText}",
          "arrival_numeric": "{arrivalDate}",
          "arrival_text": "{arrivalDateText}",
          "arrival_source": "booking.start instant converted to tenant timezone before formatting",
          "missing_booking_or_start": "empty string for arrival variables",
          "source": "booking.end instant converted to tenant timezone before formatting",
          "numeric_format": "timezone-country regional short date with two-digit day/month and four-digit year",
          "numeric_examples": {
            "Europe/Oslo": "18.09.2026",
            "America/New_York": "09/18/2026",
            "Europe/London": "18/09/2026"
          },
          "text_format": "dd MMM yyyy, lowercase English month; example 18 sep 2026",
          "missing_booking_or_end": "empty string",
          "missing_or_invalid_timezone": "UTC",
          "unmapped_or_unsupported_country_format": "yyyy-MM-dd",
          "guest_language_affects_date_format": false,
          "scope": [
            "subject/title",
            "general body",
            "email body",
            "SMS body",
            "inserted room instructions",
            "manual booking overrides",
            "booking message preview"
          ],
          "preview": "POST /api/bookings/bookings/{bookingId}/message-preview",
          "verification": "GET /api/automation/messages/logs/bookings/{bookingId}",
          "compatibility": "departureDate changes from UTC ISO date to tenant-local regional date; guest-portal variables unchanged"
        },
        "backward_compatible": true
      }
    },
    "separate_not_runner_contract": [
      "crm-controllers",
      "provider-integration-controllers",
      "incoming-webhooks",
      "internal-routes",
      "webhook-gateway",
      "virtual-gateway-simulator"
    ]
  },
  "risk_classes": {
    "read_only": {
      "approval": "not-required-by-default",
      "examples": [
        "inventory",
        "state",
        "history",
        "metering",
        "queues"
      ]
    },
    "reversible": {
      "approval": "confirm-target-and-bounds",
      "examples": [
        "temperature-target",
        "ordinary-short-pulse"
      ]
    },
    "security_sensitive": {
      "approval": "explicit-required",
      "examples": [
        "access-codes",
        "users",
        "permissions"
      ]
    },
    "destructive": {
      "approval": "explicit-confirmation-required",
      "examples": [
        "delete-device",
        "delete-tenant",
        "delete-all-codes",
        "delete-queue-data"
      ]
    },
    "ownership_changing": {
      "approval": "explicit-required",
      "examples": [
        "claim-gateway",
        "claim-device"
      ]
    },
    "operationally_dangerous": {
      "approval": "purpose-safe-conditions-and-explicit-approval-required",
      "examples": [
        "persistent-relay",
        "persistent-lock",
        "wifi-change",
        "firmware-update",
        "scheduled-lock-automation"
      ]
    }
  },
  "discovery_sequence": [
    "GET /api/gateways",
    "GET /api/sensor",
    "GET /api/gateways/{gatewayId}/sensors",
    "GET /api/sensor/{deviceId}/pairings"
  ],
  "verification_endpoints": {
    "tenant_queue": "GET /api/gateways/getqueue",
    "device_queue": "GET /api/gateways/queue/device/{deviceId}",
    "device_queue_transfer_packages": "GET /api/gateways/queue/device/{deviceId}/packages",
    "gateway_queue": "GET /api/gateways/{gatewayId}/gwqueue",
    "tenant_events": "GET /api/events",
    "device_events": "GET /api/events/sensor/{sensorId}",
    "room_events": "GET /api/events/byRoom/{roomId}",
    "paged_events": "GET /api/events/page"
  },
  "event_contract": {
    "scope": "tenant-bound",
    "paged_events": {
      "endpoint": "GET /api/events/page",
      "allowed_roles": [
        "Receptionist",
        "Restricted"
      ],
      "empty_roles_allow_unrestricted_access": true,
      "receptionist_access_codes": "censored-for-all-page-filters",
      "authentication_failure": "401 Unauthorized",
      "role_denial": "403 Forbidden",
      "authentication_or_role_failure_retry": "correct-authentication-or-permissions-first",
      "risk": "low",
      "approval": "not-required",
      "idempotent": true,
      "retry": "safe-read-deduplicate-event-ids-between-offset-pages",
      "pagination": {
        "page": "zero-based-default-0-minimum-0",
        "size": "default-40-range-1-100",
        "response_fields": [
          "content",
          "number",
          "size",
          "totalElements",
          "last"
        ],
        "order": [
          "createdDate-desc",
          "id-desc"
        ]
      },
      "filters": {
        "mutually_exclusive": [
          "sensorUuid",
          "roomId",
          "bookingId"
        ],
        "from_to": "optional-pair-inclusive-ISO-8601-event-creation-time",
        "room_requires_time_range": true
      },
      "booking_filter": {
        "parameter": "bookingId",
        "identifier": "Booking.bookingId-not-database-id",
        "match": "union-of-exact-data.bookingId-and-unlinked-recorded-code-events-before-database-pagination",
        "time_range_required": false,
        "current_booking_lookup": false,
        "deleted_bookings": "retained-matching-events-remain-readable",
        "no_matches": "200-empty-content-totalElements-0-including-unknown-booking-IDs",
        "invalid_input": "400-for-blank-bookingId-conflicting-filters-invalid-pagination-or-date-bounds",
        "included": [
          "booking-created-updated-checked-out-deleted-events-with-matching-data.bookingId",
          "sent-message-events-with-matching-data.bookingId",
          "device-events-including-credential-results-with-matching-data.bookingId",
          "unlinked-credential-result-and-code-add-remove-events-matching-recorded-booking-codes-within-recorded-stay-windows"
        ],
        "excluded": [
          "unlinked-events-not-matching-recorded-code-and-stay-window",
          "code-inference-for-events-linked-to-another-booking",
          "integration-request-logs",
          "booking_history-snapshots"
        ],
        "coverage": "partial-recorded-timeline-not-complete-field-change-audit",
        "empty_result_meaning": "no-matching-recorded-events-not-proof-of-no-activity",
        "physical_entry_proof": false,
        "verification": "read-content-totalElements-last-follow-pages-deduplicate-IDs-verify-physical-actions-separately",
        "side_effects": "none-no-command-or-queue-entry",
        "sensitive_fields": [
          "contacts",
          "message-bodies",
          "credential-identifiers",
          "access-codes"
        ],
        "code_correlation": {
          "code_source": "data.code-from-all-retained-directly-linked-events-independent-of-page-and-requested-date-bounds",
          "code_match": "exact-string-preserving-leading-zeros",
          "window_source": "all-valid-inclusive-data.start-data.end-stay-windows-in-retained-directly-linked-events",
          "event_time": "createdDate",
          "credential_result_actions": {
            "action": 33,
            "sub_actions": [
              8,
              9,
              12,
              13
            ]
          },
          "code_change_actions": [
            1028,
            1029
          ],
          "requires_unlinked_event": "data.bookingId-missing-null-or-empty",
          "device_filter": "none-within-tenant",
          "missing_code_or_valid_stay_window": "directly-linked-events-only",
          "invalid_windows": "ignore-missing-malformed-or-reversed-bounds",
          "request_date_bounds": "apply-to-direct-and-inferred-results-after-code-discovery",
          "deduplication": "single-union-query-before-pagination",
          "stored_events_modified": false,
          "response_booking_id_added": false,
          "client_policy": "do-not-discard-returned-events-without-data.bookingId",
          "saved_booking_links": "primary-gateway-attempts-assignment-at-ingestion-from-current-room-code-booking-assignment",
          "certainty": "code-reuse-within-recorded-stay-can-make-inference-ambiguous"
        }
      }
    },
    "required_headers": [
      "Authorization: Bearer sat_<TOKEN>",
      "Tenant: <TENANT_ID>"
    ],
    "interpretation": "interpret-sub_action-in-action-context-and-prefer-structured-data-over-reason-text",
    "protocol_actions": {
      "0": "gateway_online",
      "1": "button_pressed",
      "2": "passive_alarm_triggered",
      "3": "active_alarm_triggered",
      "4": "temperature_high",
      "5": "unusual_motion",
      "6": "battery_low",
      "7": "power_surge",
      "8": "water_leakage",
      "9": "unauthorized_access",
      "10": "door_left_open",
      "11": "ventilation_anomaly",
      "12": "freezing_temperature",
      "13": "high_air_pressure",
      "14": "temperature_too_low",
      "15": "device_online",
      "16": "device_offline",
      "17": "gateway_status",
      "18": "test",
      "19": "alarm_cleared",
      "20": "update_advertising_profile",
      "21": "firmware_update",
      "22": "firmware_update_chunk",
      "23": "firmware_update_chunk_done",
      "24": "restart_node",
      "25": "new_node",
      "26": "ask_for_time",
      "27": "set_time",
      "28": "pulse_relay_milliseconds",
      "29": "pulse_relay_seconds",
      "30": "pulse_relay_open",
      "31": "pulse_relay_close",
      "32": "pulse_relay_minutes",
      "33": "lock_operation",
      "34": "wall_thermostat_operation",
      "35": "restart",
      "36": "toggle_restart_mode_on",
      "37": "toggle_restart_mode_off",
      "38": "gateway_ping_with_status",
      "39": "gateway_metering_data",
      "40": "pulse_relay_count"
    },
    "application_actions": {
      "1024": {
        "name": "cleaning_marked_cleaned",
        "state": "cleaned",
        "entity_type": "room"
      },
      "1025": {
        "name": "cleaning_marked_dirty",
        "state": "dirty",
        "entity_type": "room"
      },
      "1026": {
        "name": "gateway_marked_online",
        "state": "online",
        "entity_type": "gateway"
      },
      "1027": {
        "name": "gateway_marked_offline",
        "state": "offline",
        "entity_type": "gateway"
      },
      "1028": {
        "name": "smart_lock_code_added",
        "state": "added",
        "entity_type": "device",
        "sensitive_data_keys": [
          "code",
          "mifareUid",
          "credentialId"
        ],
        "sub_action_14_means_mifare_credential": true
      },
      "1029": {
        "name": "smart_lock_code_removed",
        "state": "removed",
        "entity_type": "device",
        "sensitive_data_keys": [
          "code",
          "mifareUid",
          "credentialId"
        ]
      },
      "1030": {
        "name": "booking_message_sent",
        "entity_types": [
          "room",
          "booking_message"
        ],
        "sensitive_data_keys": [
          "code",
          "message",
          "emailMessage",
          "smsMessage",
          "recipient",
          "recipientEmail",
          "recipientPhone"
        ]
      },
      "1031": {
        "name": "sensor_restart_mode_on",
        "state": "on",
        "entity_type": "device"
      },
      "1032": {
        "name": "sensor_restart_mode_off",
        "state": "off",
        "entity_type": "device"
      },
      "1033": {
        "name": "booking_created",
        "state": "created",
        "entity_type": "booking"
      },
      "1034": {
        "name": "booking_updated",
        "states": [
          "updated",
          "checked_out"
        ],
        "entity_type": "booking",
        "checkout_detection": "require-data.state-checked_out-do-not-infer-from-current-checkedOut-value"
      },
      "1035": {
        "name": "booking_deleted",
        "state": "deleted",
        "entity_type": "booking"
      },
      "1036": {
        "name": "lock_automation_executed",
        "state": "queued",
        "entity_type": "device"
      },
      "1037": {
        "name": "lock_automation_failed",
        "state": "producer-status-or-failed-message",
        "entity_type": "device"
      }
    },
    "sub_actions": {
      "33_lock_operation": {
        "1": "pulse_open",
        "2": "open",
        "3": "close",
        "4": "add_codes",
        "5": "remove_codes",
        "6": "set_configuration",
        "7": "delete_all_codes",
        "8": "code_valid",
        "9": "code_invalid",
        "10": "pair_with_devices",
        "11": "fetch_paired_devices",
        "12": "extended_credential_valid",
        "13": "extended_credential_invalid",
        "14": "add_extended_credential",
        "15": "closed_by_star"
      },
      "34_wall_thermostat_operation": {
        "1": "set_wifi",
        "2": "set_target_temperature",
        "3": "turn_on",
        "4": "turn_off",
        "5": "restart",
        "6": "delete_wifi",
        "7": "receive_debug_data"
      },
      "39_gateway_metering_data": {
        "12": "five_minute",
        "13": "hourly",
        "14": "total",
        "15": "consumption_changed"
      }
    },
    "common_data_keys": [
      "slot",
      "valid",
      "factorCount",
      "credentialType",
      "credentialId",
      "mifareUid",
      "walletPlatform",
      "entityType",
      "entityId",
      "entityName",
      "state",
      "actorUserId",
      "roomId",
      "bookingId",
      "code",
      "triggerId",
      "taskId",
      "taskName",
      "trigger",
      "occurrence",
      "channels",
      "message",
      "emailMessage",
      "smsMessage",
      "recipient",
      "recipientEmail",
      "recipientPhone"
    ],
    "safety": {
      "event_presence_is_not_physical_completion": true,
      "queued_state_is_not_completed": true,
      "access_codes_and_message_recipient_content_are_sensitive": true
    }
  },
  "forbidden_secret_output": [
    "solvotix_sat_api_token",
    "private_key",
    "session_cookie",
    "wifi_password",
    "smart_lock_access_code",
    "smart_lock_system_code",
    "smart_lock_mifare_uid",
    "any_internal_api_token"
  ],
  "api_user_lifecycle": {
    "managed_by": "authenticated regular user through Solvotix portal",
    "management_url": "https://portal.solvotix.org/home/settings#system-users",
    "api_user_can_manage_api_users": false,
    "rotate_invalidates_old_token_immediately": true,
    "revoked_token_result": "401 Unauthorized",
    "scopes_supported": false,
    "roles_supported": true,
    "roles_shared_with_human_users": true,
    "role_update_endpoint": "PUT /api/api-users/{id}/roles",
    "access_level": "role-controlled authenticated access within bound tenant"
  },
  "token_storage": {
    "permitted": [
      "secrets-manager",
      "protected-server-environment-variable"
    ],
    "forbidden": [
      "browser-code",
      "git",
      "url",
      "logs",
      "analytics",
      "error-reports"
    ],
    "on_exposure": "rotate-immediately"
  },
  "lost_gateway_replacement_request": {
    "endpoint": "POST /api/gateways/{id}/replacement-request",
    "operation_class": "external-email-notification",
    "authentication": "tenant-bound-bearer-token-and-Tenant-header",
    "precondition": "gateway-registered-to-authenticated-tenant-and-tenant-has-name",
    "request_body": null,
    "recipient": "boggibill@gmail.com",
    "subject": "New gateway request",
    "email_content": "stored-tenant-name-gateway-name-gateway-description-and-verified-gateway-id",
    "success_status": 204,
    "success_meaning": "mail-service-accepted-message-not-recipient-delivery-or-order",
    "missing_gateway_or_tenant_status": 404,
    "mail_failure_status": "5xx",
    "deletes_gateway": false,
    "automatic_retry": false,
    "retry_policy": "do-not-retry-ambiguous-response-email-may-already-have-been-sent",
    "subsequent_removal": "separate-user-confirmed-DELETE-/api/gateways/{id}-with-verification"
  },
  "gateway_removal_policy": {
    "delete_endpoint": "DELETE /api/gateways/{id}",
    "operation_class": "ownership-changing",
    "approval_required": true,
    "authentication": "tenant-bound-bearer-token-and-Tenant-header",
    "request_body": null,
    "success_status": 204,
    "absent_or_other_tenant_status": 404,
    "effects": [
      "remove-tenant-gateway-registration",
      "release-global-gateway-claim",
      "remove-runtime-gateway-state",
      "disconnect-registered-transports",
      "clear-cached-gateway-queue",
      "release-node-connection-ownership"
    ],
    "incoming_traffic_can_claim_gateway": false,
    "factory_reset": false,
    "deletes_associated_devices_or_device_ownership": false,
    "purges_historical_events_or_metering": false,
    "confirms_cancellation_of_commands_on_hardware": false,
    "verification": [
      "GET /api/gateways/{id} returns 404 in old tenant",
      "gateway absent from GET /api/gateways in old tenant"
    ],
    "dedicated_deletion_event": null,
    "automatic_retry": false,
    "retry_policy": "read-state-after-ambiguous-response; repeated-delete-while-absent-returns-404",
    "reclaim_endpoint": "POST /api/gateways/{id}/{name}",
    "reclaim_context": "new-tenant-authorized-credentials-and-Tenant-header",
    "reclaim_verification": "non-null-200-response-and-gateway-present-in-destination-tenant"
  },
  "account_tenant_gateway_cleanup_policy": {
    "account_delete_endpoint": "DELETE /api/users/{id}/account",
    "account_scope": "all-persisted-tenant-memberships-of-user",
    "account_request_body": null,
    "account_success": "200-empty-body",
    "tenant_delete_endpoint": "DELETE /api/tenants",
    "tenant_request_body": {
      "id": "<TARGET_TENANT_ID>"
    },
    "tenant_success": "200-echoed-Tenant-body-does-not-prove-deletion",
    "operation_class": "destructive",
    "approval_required": true,
    "authentication": "authorized-bearer-token-and-Tenant-header",
    "gateway_cleanup_condition": "tenant-has-no-remaining-users",
    "shared_tenant_gateways_retained": true,
    "gateway_cleanup": "gateway_removal_policy",
    "includes_claims_without_runtime_gateway": true,
    "reclaim_endpoint": "POST /api/gateways/{id}/{name}",
    "factory_reset": false,
    "dedicated_gateway_deletion_event": null,
    "automatic_retry": false,
    "atomic": false,
    "verification": "inspect-remaining-memberships-and-authorized-gateway-state-or-approved-destination-claim",
    "authorization_failure_proves_cleanup": false,
    "individual_gateway_history_retention_applies_to_full_tenant_cleanup": false
  },
  "gateway_offline_warning_delay": {
    "update_endpoint": "PUT /api/gateways/{id}",
    "gateway_selection": "URL id; body id ignored",
    "field": "pushNotificationDelayMinutes",
    "unit": "minutes",
    "default": 5,
    "positive_values_only": true,
    "authentication": "tenant-bound-bearer-token-and-Tenant-header",
    "verification": "GET /api/gateways/{id}",
    "approval_required": false,
    "offline_event_action": 1027
  },
  "automated_message_room_filter_policy": {
    "configuration_endpoints": [
      "POST /api/automation/messages/triggers",
      "PUT /api/automation/messages/triggers/{id}"
    ],
    "request_field": "roomIds",
    "authentication": "bearer-plus-tenant-context",
    "requires": "nonempty-list-requires-sendToBookingGuest=true",
    "matching": "exact-booking-roomId-after-trimming-and-deduplicating-configured-IDs",
    "create_default": "all-rooms",
    "update_null_or_omitted": "preserve-existing-filter",
    "empty_list": "all-rooms",
    "missing_booking_room": "excluded-by-nonempty-filter",
    "validation_errors": "HTTP-400-for-null-or-blank-entries-or-nonempty-filter-without-booking-guest-delivery",
    "evaluation": "after-trigger-time-eligibility-before-contact-cleaning-payment-and-dispatch",
    "roomMessages": "content-overrides-only-independent-of-roomIds",
    "warning": "5=ROOM_NOT_INCLUDED-only-for-due-excluded-bookings-without-any-successful-automated-message",
    "failure_precedence": [
      "ROOM_NOT_CLEAN",
      "NOT_PAID",
      "NO_RECIPIENT_CHANNEL",
      "DISPATCH_FAILED",
      "ROOM_NOT_INCLUDED"
    ],
    "successful_delivery_precedence": "any-successful-rule-clears-warning-regardless-of-rule-order",
    "cleaning_preview": "only-rules-matching-booking-roomId",
    "reevaluation": "approximately-every-minute-and-on-booking-import-update-within-existing-trigger-window",
    "exclusion_side_effects": "no-delivery-log-event-or-deferred-queue-entry",
    "deduplication": "existing-delivered-channel-deduplication-unchanged",
    "risk_class": "guest-communication-policy-with-outbound-sending-effects",
    "approval_required": true,
    "post_retry": "verify-current-configuration-before-retrying-ambiguous-create",
    "put_retry": "verify-current-configuration-before-retry",
    "verification": [
      "GET /api/automation/messages/triggers",
      "GET /api/bookings",
      "GET /api/automation/messages/logs/bookings/{bookingId}"
    ],
    "physical_operation": false
  },
  "configuration_display_defaults_policy": {
    "service": "integrations-process",
    "runner_api_user_tokens_supported": false,
    "tenant_body_or_query_argument": false,
    "catalog": [
      {
        "base_path": "/integrations/gibbs",
        "settings_read": "GET /settings",
        "settings_write": "POST /settings",
        "new_record_enabled_default": false
      }
    ],
    "existing_saved_enabled_preserved": true,
    "read_initializes_missing_settings_and_token": true,
    "read_and_save_ensure_default_code_picker": true,
    "enabled_flag_controls_configuration_display": true,
    "webhooks_enforce_enabled_flag": false,
    "response_includes_secret_token": true,
    "save_omitted_enabled_preserves_value": true,
    "verification": "Read settings after saving and compare enabled; the display flag does not verify callback shutdown."
  },
  "provider_configuration_and_sync_policy": {
    "service": "integrations-process",
    "runner_api_contract": false,
    "applies_only_to_cataloged_operations": true,
    "catalog": [
      {
        "base_path": "/integrations/lodgify",
        "settings_read": "GET /settings",
        "settings_write": "POST /settings",
        "property_discovery": "GET /properties",
        "room_discovery": "GET /rooms",
        "preview": "POST /sync/test",
        "apply": "POST /sync",
        "disconnect": "DELETE /auth",
        "integration_log_search": "lodgify",
        "webhook_settings_read": "GET /webhooks",
        "webhook_settings_write": "POST /webhooks",
        "webhook_disconnect": "DELETE /webhooks",
        "webhook_retry": "POST /webhooks/retry",
        "provider_callback": "POST /webhooks/lodgify/{token}",
        "webhook_callback_base_property": "lodgify.webhook-callback-base-url",
        "webhook_callback_base_default": "https://webhook.solvotix.org/webhooks/lodgify"
      }
    ],
    "authentication": {
      "bearer": "Firebase ID token",
      "session_cookie": "solvotix_session",
      "tenant_header": "Tenant",
      "tenant_membership_required": true,
      "runner_api_user_tokens_supported": false,
      "tenant_body_or_query_argument": false
    },
    "settings": {
      "request_fields": [
        "apiKey",
        "propertyId",
        "enabled"
      ],
      "response_fields": [
        "configured",
        "enabled",
        "propertyId"
      ],
      "plaintext_key_returned": false,
      "initial_key_required": true,
      "omitted_key_on_update": "preserve",
      "blank_key": "400",
      "null_or_omitted_property": "all-accessible-properties",
      "initial_enabled_default": true,
      "omitted_enabled_on_update": "preserve",
      "save_validates_provider_key": false,
      "approval_required": true,
      "retry": "read-settings-before-repeating-uncertain-save",
      "key_replacement_with_owned_subscriptions": "409-remove-webhooks-before-replacing"
    },
    "sync_request": {
      "required_fields": [
        "start",
        "end"
      ],
      "format": "ISO-8601-timestamp-with-offset",
      "start_must_precede_end": true,
      "window": "[start,end)",
      "overlap": "arrival < end AND departure > start; also consider previously saved stay dates",
      "booking_status_filter": "none; all-or-missing-status-values",
      "status_changes_trigger_deletion": false,
      "explicit_cancellation_or_trash": "is_deleted=true-or-non-null-canceled_at; prevent-import-and-remove-existing-records-in-scope"
    },
    "preview": {
      "risk": "read-only",
      "approval_required": false,
      "works_while_disabled": true,
      "writes": false,
      "executes_booking_filters_or_automation": false,
      "response_status": 200,
      "dryRun": true,
      "retry": "allowed-with-backoff"
    },
    "apply": {
      "risk": "booking-access-and-automated-message-effects",
      "approval_required": true,
      "requires_enabled": true,
      "response_status": 200,
      "dryRun": false,
      "atomic": false,
      "automatic_retry": false,
      "record_idempotency": "stable-provider-prefixed-identifiers",
      "side_effects_exactly_once": false,
      "missing_list_entries_trigger_deletion": false,
      "room_splitting": false,
      "all_imported_statuses_execute_existing_filters_and_automation": true,
      "ambiguous_room_assignments": "skip-and-report; existing-records-remain-unchanged",
      "http_success_proves_physical_completion": false
    },
    "sync_response_fields": [
      "start",
      "end",
      "dryRun",
      "scanned",
      "matched",
      "bookings",
      "deletions",
      "skipped",
      "categories",
      "rooms",
      "unsupportedRoomTypes",
      "warnings"
    ],
    "warning_limit": 100,
    "delivery": {
      "mode": "configured-webhooks-with-scheduled-polling-and-manual-sync",
      "default_fixed_delay_ms": 600000,
      "default_window": "tenant-local-yesterday-through-end-of-third-following-day",
      "webhook_subscription": true,
      "provider_writeback": false,
      "new_event_types": false
    },
    "disconnect": {
      "success_status": 204,
      "approval_required": true,
      "idempotent": true,
      "clears_local_key": true,
      "disables_import": true,
      "revokes_provider_key": false,
      "cancels_inflight_sync": false,
      "removes_imported_bookings_or_codes": false,
      "stops_shared_booking_automation": false,
      "removes_owned_provider_subscriptions": true,
      "cleanup_failure": "callbacks-and-future-imports-disabled-key-and-records-retained-for-retry"
    },
    "verification": [
      "GET settings",
      "GET webhook setup and work status",
      "existing-booking-and-room-state",
      "GET /integrations/logs",
      "message-delivery-records",
      "device-events-and-queues-if-physical-effects-occurred"
    ],
    "errors": {
      "400": "missing-context-or-settings-invalid-input-or-disabled-apply",
      "401": "authentication",
      "403": "tenant-membership",
      "429": "provider-rate-limit",
      "502": "provider-rejection-or-invalid/incomplete-pagination",
      "503": "provider-unavailable-interrupted-or-callback-base-not-configured",
      "500": "possible-partial-database-or-automation-failure",
      "409": "key-replacement-before-webhook-cleanup-callback-configuration-conflict-or-no-failed-work"
    },
    "webhooks": {
      "management_authentication": "same-as-provider-configuration",
      "tenant_argument": false,
      "configuration": {
        "request_fields": [
          "enabled",
          "events"
        ],
        "enabled_required": true,
        "omitted_events": "all-supported-booking-events",
        "empty_or_unknown_enabled_events": "400",
        "event_discovery": "supportedEvents-in-GET-response",
        "response_status": 200,
        "approval_required": true,
        "atomic": false,
        "retry": "read-status-and-repeat-same-configuration-to-reconcile-saved-unique-callbacks",
        "starts_booking_sync": false,
        "concurrent_configuration_across_replicas_serialized": false,
        "saved_credentials": "provider-subscription-id-and-once-only-secret",
        "frontend_supplied_callback_host": false
      },
      "response_fields": [
        "enabled",
        "events",
        "supportedEvents",
        "subscriptions",
        "work"
      ],
      "subscription_fields": [
        "event",
        "subscriptionId",
        "enabled",
        "registered",
        "cleanupRequired",
        "secretStored"
      ],
      "subscription_state_is_live_provider_check": false,
      "secrets_and_callback_urls_returned": false,
      "lost_creation_response": "provider-secret-may-be-unrecoverable-but-url-capability-remains-usable",
      "callback": {
        "authentication": "random-256-bit-url-capability",
        "provider_hmac_verified": false,
        "bearer_or_session_required": false,
        "tenant_header_required": false,
        "tenant_routing": "saved-subscription-only",
        "body": "ignored-no-required-fields",
        "booking_data_source": "authenticated-provider-api",
        "accepted_status": 202,
        "unknown_or_disabled_status": 404,
        "persistence_failure_status": 500,
        "acknowledgement": "majority-journal-persisted-notification-not-completed-sync",
        "proxy_access_logs": "redact-callback-capability",
        "frontend_test_endpoint": false
      },
      "processing": {
        "scope": "saved-properties-all-stay-dates",
        "idle_worker_check_seconds": 1,
        "latency_guaranteed": false,
        "pending_notifications": "coalesced",
        "notifications_during_processing": "another-pass-remains-pending",
        "disabled_settings": "consume-with-disabled-outcome; authorize-manual-sync-for-backfill",
        "failure_or_expired_lease": "block-for-operator-review",
        "worker_leases": "shared-database; manual-and-polling-sync-only-serialized-per-process",
        "exactly_once_side_effects": false,
        "atomic_apply": false
      },
      "work_fields": [
        "pending",
        "processing",
        "reviewRequired",
        "lastReceivedAt",
        "lastProcessedAt",
        "lastOutcome",
        "lastError"
      ],
      "work_outcomes": [
        "synced",
        "disabled",
        "review_required",
        null
      ],
      "retry": {
        "request_body": false,
        "requires_enabled_setup_and_import": true,
        "approval_required": true,
        "precondition": "inspect-booking-integration-message-and-access-state-after-possible-partial-apply",
        "success_status": 202,
        "repeated_while_pending": "coalesce",
        "no_failed_or_pending_work_status": 409,
        "success_proves_physical_delivery": false
      },
      "disable": {
        "delete_success_status": 204,
        "post_disabled_success_status": 200,
        "local_callbacks_disabled_before_remote_cleanup": true,
        "only_owned_subscriptions_removed": true,
        "cleanup_failure_retains_credentials_and_records": true,
        "keeps_polling_and_imported_data": true,
        "cancels_inflight_sync": false,
        "verification": "enabled-false-and-empty-subscription-list",
        "reregister_rotates_callback_tokens": true
      }
    }
  }
}
