openapi: 3.0.3
info:
  title: Lattix SDK Control Plane API
  version: bootstrap
  description: |
    Authoritative machine-readable contract for the public `/v1/sdk/*` routes exposed by
    `lattix-platform-api`.

    These endpoints are intentionally metadata-only control-plane contracts. SDKs use them to
    discover capabilities, resolve policy, obtain key-handling guidance, register protected
    artifacts, and emit evidence without sending routine customer plaintext through the platform
    API.
servers:
  - url: /
tags:
  - name: discovery
    description: Caller introspection, capability discovery, and bootstrap metadata.
  - name: session
    description: SDK client credential exchange for short-lived bearer tokens.
  - name: protection
    description: Metadata-only planning for protection, policy, and key access workflows.
  - name: registration
    description: Protected artifact registration after local enforcement.
  - name: evidence
    description: Metadata-only evidence ingestion for protected artifact lifecycle events.
paths:
  /v1/sdk/capabilities:
    get:
      tags: [discovery]
      summary: Get SDK control-plane capabilities
      description: |
        Returns the resolved caller identity, active authentication mode, deployment-default
        scopes, and configured public platform domains available to the SDK.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      responses:
        '200':
          description: SDK capabilities resolved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkCapabilitiesResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/bootstrap:
    get:
      tags: [discovery]
      summary: Get SDK bootstrap metadata
      description: |
        Describes the embedded-enforcement model, supported operations, supported protected artifact
        profiles, and the control-plane domains an SDK may need to call during local protection.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      responses:
        '200':
          description: SDK bootstrap metadata returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkBootstrapResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/whoami:
    get:
      tags: [discovery]
      summary: Resolve caller identity
      description: Returns the tenant, principal, subject, and scopes as resolved by the facade.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      responses:
        '200':
          description: Caller identity resolved successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallerIdentityResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/session:
    post:
      tags: [session]
      summary: Exchange SDK client credentials for a short-lived bearer token
      description: |
        Validates SDK client credentials with the internal verifier and returns a short-lived JWT
        suitable for calling the remaining `/v1/sdk/*` routes in bearer-token deployments.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkSessionExchangeRequest'
      responses:
        '200':
          description: SDK session token issued successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkSessionExchangeResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
        '429':
          description: SDK session rate limit exceeded.
          headers:
            Retry-After:
              description: Seconds before the client should retry token exchange.
              schema:
                type: integer
                format: int64
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          $ref: '#/components/responses/ErrorResponse'
        '502':
          $ref: '#/components/responses/ErrorResponse'
        '503':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/protection-plan:
    post:
      tags: [protection]
      summary: Get a metadata-only protection plan
      description: |
        Accepts only workload, resource, and artifact metadata for a proposed protection workflow.
        Plaintext content is intentionally out of contract.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkProtectionPlanRequest'
      responses:
        '200':
          description: Protection plan returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkProtectionPlanResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/policy-resolve:
    post:
      tags: [protection]
      summary: Resolve policy from metadata
      description: |
        Resolves authorization and handling guidance from metadata only so the SDK can enforce the
        result locally.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkPolicyResolveRequest'
      responses:
        '200':
          description: Policy guidance returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkPolicyResolveResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/key-access-plan:
    post:
      tags: [protection]
      summary: Get key access guidance
      description: |
        Accepts metadata for wrap, unwrap, or rewrap flows and returns how the SDK should perform
        local cryptographic work while the platform authorizes key use.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkKeyAccessPlanRequest'
      responses:
        '200':
          description: Key access plan returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkKeyAccessPlanResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/artifact-register:
    post:
      tags: [registration]
      summary: Register a protected artifact
      description: |
        Registers the resulting protected artifact metadata after local enforcement. The contract
        accepts protected artifact references and metadata only.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkArtifactRegisterRequest'
      responses:
        '200':
          description: Artifact registration guidance returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkArtifactRegisterResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
  /v1/sdk/evidence:
    post:
      tags: [evidence]
      summary: Ingest metadata-only evidence
      description: |
        Records evidence events associated with protected artifacts, policy decisions, and local
        enforcement outcomes without transmitting plaintext payloads.
      security:
        - BearerAuth: []
        - TrustedHeaders: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SdkEvidenceIngestRequest'
      responses:
        '200':
          description: Evidence ingestion guidance returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SdkEvidenceIngestResponse'
        '401':
          $ref: '#/components/responses/ErrorResponse'
        '403':
          $ref: '#/components/responses/ErrorResponse'
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Standard bearer-token flow for callers using JWT validation in `lattix-platform-api`.
    TrustedHeaders:
      type: apiKey
      in: header
      name: x-lattix-tenant-id
      description: |
        Trusted ingress/header mode. Deployments using this pattern also forward
        `x-lattix-user-id` when required by configuration.
  responses:
    ErrorResponse:
      description: Error response returned by `lattix-platform-api`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  schemas:
    ErrorEnvelope:
      type: object
      additionalProperties: false
      required: [error]
      properties:
        error:
          type: object
          additionalProperties: false
          required: [code, message]
          properties:
            code:
              type: string
            message:
              type: string
    AuthMode:
      type: string
      enum: [trusted_headers, bearer_token, bearer_token_or_trusted_headers]
    RequestContext:
      type: object
      additionalProperties: false
      required: [tenant_id, principal_id, subject, auth_source, scopes]
      properties:
        tenant_id:
          type: string
        principal_id:
          type: string
        subject:
          type: string
        auth_source:
          type: string
          enum: [trusted_headers, bearer_token, sdk_client_credentials]
        scopes:
          type: array
          items:
            type: string
    SdkRouteCapability:
      type: object
      additionalProperties: false
      required: [route, domain, configured, required_scopes]
      properties:
        route:
          type: string
        domain:
          type: string
        configured:
          type: boolean
        required_scopes:
          type: array
          items:
            type: string
    SdkCapabilitiesResponse:
      type: object
      additionalProperties: false
      required: [service, status, auth_mode, caller, default_required_scopes, routes]
      properties:
        service:
          type: string
        status:
          type: string
        auth_mode:
          $ref: '#/components/schemas/AuthMode'
        caller:
          $ref: '#/components/schemas/RequestContext'
        default_required_scopes:
          type: array
          items:
            type: string
        routes:
          type: array
          items:
            $ref: '#/components/schemas/SdkRouteCapability'
    CallerIdentityResponse:
      type: object
      additionalProperties: false
      required: [service, status, caller]
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
    ProtectionOperation:
      type: string
      enum: [protect, access, rewrap]
    ArtifactProfile:
      type: string
      enum: [tdf, envelope, detached_signature]
    PlatformDomainPlan:
      type: object
      additionalProperties: false
      required: [domain, configured, reason]
      properties:
        domain:
          type: string
        configured:
          type: boolean
        reason:
          type: string
    SdkBootstrapResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - auth_mode
        - caller
        - enforcement_model
        - plaintext_to_platform
        - policy_resolution_mode
        - supported_operations
        - supported_artifact_profiles
        - platform_domains
      properties:
        service:
          type: string
        status:
          type: string
        auth_mode:
          $ref: '#/components/schemas/AuthMode'
        caller:
          $ref: '#/components/schemas/RequestContext'
        enforcement_model:
          type: string
        plaintext_to_platform:
          type: boolean
        policy_resolution_mode:
          type: string
        supported_operations:
          type: array
          items:
            $ref: '#/components/schemas/ProtectionOperation'
        supported_artifact_profiles:
          type: array
          items:
            $ref: '#/components/schemas/ArtifactProfile'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
    SdkSessionExchangeRequest:
      type: object
      additionalProperties: false
      required: [tenant_id, client_id, client_secret, requested_scopes]
      properties:
        tenant_id:
          type: string
        client_id:
          type: string
        client_secret:
          type: string
        requested_scopes:
          type: array
          items:
            type: string
    SdkSessionExchangeResponse:
      type: object
      additionalProperties: false
      required: [access_token, token_type, expires_in, scope, tenant_id, client_id, subject]
      properties:
        access_token:
          type: string
        token_type:
          type: string
        expires_in:
          type: integer
          format: int64
          minimum: 0
        scope:
          type: string
        tenant_id:
          type: string
        client_id:
          type: string
        subject:
          type: string
    WorkloadDescriptor:
      type: object
      additionalProperties: false
      required: [application]
      properties:
        application:
          type: string
        environment:
          type: string
        component:
          type: string
    ResourceDescriptor:
      type: object
      additionalProperties: false
      required: [kind]
      properties:
        kind:
          type: string
        id:
          type: string
        mime_type:
          type: string
    StringMap:
      type: object
      additionalProperties:
        type: string
    SdkProtectionPlanRequest:
      type: object
      additionalProperties: false
      required: [operation, workload, resource, labels, attributes]
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload:
          $ref: '#/components/schemas/WorkloadDescriptor'
        resource:
          $ref: '#/components/schemas/ResourceDescriptor'
        preferred_artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        content_digest:
          type: string
        content_size_bytes:
          type: integer
          format: int64
          minimum: 0
        purpose:
          type: string
        labels:
          type: array
          items:
            type: string
        attributes:
          $ref: '#/components/schemas/StringMap'
    ProtectionPlanSummary:
      type: object
      additionalProperties: false
      required:
        - operation
        - workload_application
        - resource_kind
        - preferred_artifact_profile
        - content_digest_present
        - label_count
        - attribute_count
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload_application:
          type: string
        workload_environment:
          type: string
          nullable: true
        workload_component:
          type: string
          nullable: true
        resource_kind:
          type: string
        resource_id:
          type: string
          nullable: true
        mime_type:
          type: string
          nullable: true
        preferred_artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        content_digest_present:
          type: boolean
        content_size_bytes:
          type: integer
          format: int64
          nullable: true
          minimum: 0
        label_count:
          type: integer
          format: int64
          minimum: 0
        attribute_count:
          type: integer
          format: int64
          minimum: 0
        purpose:
          type: string
          nullable: true
    ProtectionPlanDecision:
      type: object
      additionalProperties: false
      required: [allow, required_scopes, handling_mode, plaintext_transport]
      properties:
        allow:
          type: boolean
        required_scopes:
          type: array
          items:
            type: string
        handling_mode:
          type: string
        plaintext_transport:
          type: string
    ProtectionExecutionPlan:
      type: object
      additionalProperties: false
      required:
        - protect_locally
        - local_enforcement_library
        - send_plaintext_to_platform
        - send_only
        - artifact_profile
        - key_strategy
        - policy_resolution
      properties:
        protect_locally:
          type: boolean
        local_enforcement_library:
          type: string
        send_plaintext_to_platform:
          type: boolean
        send_only:
          type: array
          items:
            type: string
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        key_strategy:
          type: string
        policy_resolution:
          type: string
    SdkProtectionPlanResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - caller
        - request_summary
        - decision
        - execution
        - platform_domains
        - warnings
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
        request_summary:
          $ref: '#/components/schemas/ProtectionPlanSummary'
        decision:
          $ref: '#/components/schemas/ProtectionPlanDecision'
        execution:
          $ref: '#/components/schemas/ProtectionExecutionPlan'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
        warnings:
          type: array
          items:
            type: string
    SdkPolicyResolveRequest:
      type: object
      additionalProperties: false
      required: [operation, workload, resource, labels, attributes]
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload:
          $ref: '#/components/schemas/WorkloadDescriptor'
        resource:
          $ref: '#/components/schemas/ResourceDescriptor'
        content_digest:
          type: string
        content_size_bytes:
          type: integer
          format: int64
          minimum: 0
        purpose:
          type: string
        labels:
          type: array
          items:
            type: string
        attributes:
          $ref: '#/components/schemas/StringMap'
    PolicyRequestSummary:
      type: object
      additionalProperties: false
      required:
        - operation
        - workload_application
        - resource_kind
        - content_digest_present
        - label_count
        - attribute_count
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload_application:
          type: string
        workload_environment:
          type: string
          nullable: true
        workload_component:
          type: string
          nullable: true
        resource_kind:
          type: string
        resource_id:
          type: string
          nullable: true
        mime_type:
          type: string
          nullable: true
        content_digest_present:
          type: boolean
        content_size_bytes:
          type: integer
          format: int64
          nullable: true
          minimum: 0
        purpose:
          type: string
          nullable: true
        label_count:
          type: integer
          format: int64
          minimum: 0
        attribute_count:
          type: integer
          format: int64
          minimum: 0
    PolicyResolutionDecision:
      type: object
      additionalProperties: false
      required: [allow, enforcement_mode, required_scopes, policy_inputs, required_actions]
      properties:
        allow:
          type: boolean
        enforcement_mode:
          type: string
        required_scopes:
          type: array
          items:
            type: string
        policy_inputs:
          type: array
          items:
            type: string
        required_actions:
          type: array
          items:
            type: string
    PolicyHandlingGuidance:
      type: object
      additionalProperties: false
      required: [protect_locally, plaintext_transport, bind_policy_to, evidence_expected]
      properties:
        protect_locally:
          type: boolean
        plaintext_transport:
          type: string
        bind_policy_to:
          type: array
          items:
            type: string
        evidence_expected:
          type: array
          items:
            type: string
    SdkPolicyResolveResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - caller
        - request_summary
        - decision
        - handling
        - platform_domains
        - warnings
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
        request_summary:
          $ref: '#/components/schemas/PolicyRequestSummary'
        decision:
          $ref: '#/components/schemas/PolicyResolutionDecision'
        handling:
          $ref: '#/components/schemas/PolicyHandlingGuidance'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
        warnings:
          type: array
          items:
            type: string
    KeyAccessOperation:
      type: string
      enum: [wrap, unwrap, rewrap]
    SdkKeyAccessPlanRequest:
      type: object
      additionalProperties: false
      required: [operation, workload, resource, labels, attributes]
      properties:
        operation:
          $ref: '#/components/schemas/KeyAccessOperation'
        workload:
          $ref: '#/components/schemas/WorkloadDescriptor'
        resource:
          $ref: '#/components/schemas/ResourceDescriptor'
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        key_reference:
          type: string
        content_digest:
          type: string
        purpose:
          type: string
        labels:
          type: array
          items:
            type: string
        attributes:
          $ref: '#/components/schemas/StringMap'
    KeyAccessRequestSummary:
      type: object
      additionalProperties: false
      required:
        - operation
        - workload_application
        - resource_kind
        - artifact_profile
        - key_reference_present
        - content_digest_present
        - label_count
        - attribute_count
      properties:
        operation:
          $ref: '#/components/schemas/KeyAccessOperation'
        workload_application:
          type: string
        workload_environment:
          type: string
          nullable: true
        workload_component:
          type: string
          nullable: true
        resource_kind:
          type: string
        resource_id:
          type: string
          nullable: true
        mime_type:
          type: string
          nullable: true
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        key_reference_present:
          type: boolean
        content_digest_present:
          type: boolean
        purpose:
          type: string
          nullable: true
        label_count:
          type: integer
          format: int64
          minimum: 0
        attribute_count:
          type: integer
          format: int64
          minimum: 0
    KeyAccessDecision:
      type: object
      additionalProperties: false
      required: [allow, required_scopes, operation, key_reference_present]
      properties:
        allow:
          type: boolean
        required_scopes:
          type: array
          items:
            type: string
        operation:
          $ref: '#/components/schemas/KeyAccessOperation'
        key_reference_present:
          type: boolean
    KeyAccessExecutionPlan:
      type: object
      additionalProperties: false
      required:
        - local_cryptographic_operation
        - platform_role
        - send_plaintext_to_platform
        - send_only
        - artifact_profile
        - authorization_strategy
      properties:
        local_cryptographic_operation:
          type: boolean
        platform_role:
          type: string
        send_plaintext_to_platform:
          type: boolean
        send_only:
          type: array
          items:
            type: string
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        authorization_strategy:
          type: string
    SdkKeyAccessPlanResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - caller
        - request_summary
        - decision
        - execution
        - platform_domains
        - warnings
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
        request_summary:
          $ref: '#/components/schemas/KeyAccessRequestSummary'
        decision:
          $ref: '#/components/schemas/KeyAccessDecision'
        execution:
          $ref: '#/components/schemas/KeyAccessExecutionPlan'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
        warnings:
          type: array
          items:
            type: string
    SdkArtifactRegisterRequest:
      type: object
      additionalProperties: false
      required:
        - operation
        - workload
        - resource
        - artifact_profile
        - artifact_digest
        - labels
        - attributes
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload:
          $ref: '#/components/schemas/WorkloadDescriptor'
        resource:
          $ref: '#/components/schemas/ResourceDescriptor'
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        artifact_digest:
          type: string
        artifact_locator:
          type: string
        decision_id:
          type: string
        key_reference:
          type: string
        purpose:
          type: string
        labels:
          type: array
          items:
            type: string
        attributes:
          $ref: '#/components/schemas/StringMap'
    ArtifactRegistrationSummary:
      type: object
      additionalProperties: false
      required:
        - operation
        - workload_application
        - resource_kind
        - artifact_profile
        - artifact_digest
        - artifact_locator_present
        - decision_id_present
        - key_reference_present
        - label_count
        - attribute_count
      properties:
        operation:
          $ref: '#/components/schemas/ProtectionOperation'
        workload_application:
          type: string
        workload_environment:
          type: string
          nullable: true
        workload_component:
          type: string
          nullable: true
        resource_kind:
          type: string
        resource_id:
          type: string
          nullable: true
        mime_type:
          type: string
          nullable: true
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        artifact_digest:
          type: string
        artifact_locator_present:
          type: boolean
        decision_id_present:
          type: boolean
        key_reference_present:
          type: boolean
        purpose:
          type: string
          nullable: true
        label_count:
          type: integer
          format: int64
          minimum: 0
        attribute_count:
          type: integer
          format: int64
          minimum: 0
    ArtifactRegistrationPlan:
      type: object
      additionalProperties: false
      required:
        - accepted
        - required_scopes
        - artifact_transport
        - send_plaintext_to_platform
        - catalog_actions
        - evidence_expected
      properties:
        accepted:
          type: boolean
        required_scopes:
          type: array
          items:
            type: string
        artifact_transport:
          type: string
        send_plaintext_to_platform:
          type: boolean
        catalog_actions:
          type: array
          items:
            type: string
        evidence_expected:
          type: array
          items:
            type: string
    SdkArtifactRegisterResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - caller
        - request_summary
        - registration
        - platform_domains
        - warnings
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
        request_summary:
          $ref: '#/components/schemas/ArtifactRegistrationSummary'
        registration:
          $ref: '#/components/schemas/ArtifactRegistrationPlan'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
        warnings:
          type: array
          items:
            type: string
    EvidenceEventType:
      type: string
      enum: [protect, access, rewrap, deny]
    SdkEvidenceIngestRequest:
      type: object
      additionalProperties: false
      required: [event_type, workload, resource, labels, attributes]
      properties:
        event_type:
          $ref: '#/components/schemas/EvidenceEventType'
        workload:
          $ref: '#/components/schemas/WorkloadDescriptor'
        resource:
          $ref: '#/components/schemas/ResourceDescriptor'
        artifact_profile:
          $ref: '#/components/schemas/ArtifactProfile'
        artifact_digest:
          type: string
        decision_id:
          type: string
        outcome:
          type: string
        occurred_at:
          type: string
          description: Caller-supplied event timestamp, typically RFC 3339.
        purpose:
          type: string
        labels:
          type: array
          items:
            type: string
        attributes:
          $ref: '#/components/schemas/StringMap'
    EvidenceIngestSummary:
      type: object
      additionalProperties: false
      required:
        - event_type
        - workload_application
        - resource_kind
        - artifact_digest_present
        - decision_id_present
        - label_count
        - attribute_count
      properties:
        event_type:
          $ref: '#/components/schemas/EvidenceEventType'
        workload_application:
          type: string
        workload_environment:
          type: string
          nullable: true
        workload_component:
          type: string
          nullable: true
        resource_kind:
          type: string
        resource_id:
          type: string
          nullable: true
        mime_type:
          type: string
          nullable: true
        artifact_profile:
          allOf:
            - $ref: '#/components/schemas/ArtifactProfile'
          nullable: true
        artifact_digest_present:
          type: boolean
        decision_id_present:
          type: boolean
        outcome:
          type: string
          nullable: true
        occurred_at:
          type: string
          nullable: true
        purpose:
          type: string
          nullable: true
        label_count:
          type: integer
          format: int64
          minimum: 0
        attribute_count:
          type: integer
          format: int64
          minimum: 0
    EvidenceIngestionPlan:
      type: object
      additionalProperties: false
      required: [accepted, required_scopes, plaintext_transport, send_only, correlate_by]
      properties:
        accepted:
          type: boolean
        required_scopes:
          type: array
          items:
            type: string
        plaintext_transport:
          type: string
        send_only:
          type: array
          items:
            type: string
        correlate_by:
          type: array
          items:
            type: string
    SdkEvidenceIngestResponse:
      type: object
      additionalProperties: false
      required:
        - service
        - status
        - caller
        - request_summary
        - ingestion
        - platform_domains
        - warnings
      properties:
        service:
          type: string
        status:
          type: string
        caller:
          $ref: '#/components/schemas/RequestContext'
        request_summary:
          $ref: '#/components/schemas/EvidenceIngestSummary'
        ingestion:
          $ref: '#/components/schemas/EvidenceIngestionPlan'
        platform_domains:
          type: array
          items:
            $ref: '#/components/schemas/PlatformDomainPlan'
        warnings:
          type: array
          items:
            type: string