
# 연결 리비전 게시

`POST /v1/connections/{connection_id}/revisions/{revision_id}:publish` · 권한 `connections:write`

초안 리비전을 엔터프라이즈 연결의 라이브 설정으로 만듭니다. 한 번의 단계에서 리비전의 내용이 현재 라이브 설정을 대체합니다:

- SAML: ID 공급자의 entity ID, SSO 및 SLO URL, 리비전의 서명 인증서;
- OIDC: 클라이언트 필드와, 리비전에 포함된 경우 새 클라이언트 시크릿;
- SP 호스트 마이그레이션: SP 호스트와 SP URL. 이전 호스트는 30일 동안 계속 응답하며, 그 후 `404`를 반환합니다.

리비전에는 최근 24시간 이내의 **해당 리비전에 대한 통과한 테스트 로그인**이 있어야 합니다. [연결 테스트](test.md)에서 `revision_id`와 함께 테스트를 시작하고 브라우저에서 완료하십시오. 라이브 설정에 대한 테스트는 인정되지 않습니다.

이미 게시된 리비전을 다시 게시하면 아무것도 기록되지 않으며 `already_published: true`와 함께 `200`을 반환합니다. 동시에 들어온 두 게시 요청 중 하나만 기록됩니다. 이 게시는 `connection.revision_published`로 감사 기록됩니다.

요청 본문은 없습니다(보내지 않거나 `{}`를 보내십시오). `If-Match`도 사용하지 않습니다. 리비전에는 버전이 없습니다. 초안을 만든 후 라이브 설정이 변경되었다면 게시가 거부되므로 새 초안을 만드십시오.

## 요청

| 필드 | 유형 | 필수 | 설명 |
|---|---|---|---|
| `connection_id` | path | 예 | 엔터프라이즈 연결 ID (`conn_…`). |
| `revision_id` | path | 예 | [리비전 목록 조회](revisions.md)에서 확인한 리비전 ID (`connrev_…`). |
| `Idempotency-Key` | header | 아니요 | 요청을 재시도해도 안전하도록 하는 선택적 키 (16-64자). |

## 응답

`200 OK`:

```json
{
  "revision": {
    "id": "connrev_01j9xr8c2d4e6f8g0h2j4k6m8n",
    "connection_id": "conn_01j9xp6q0r1s5t7v9w1x3y5z7b",
    "protocol": "saml",
    "kind": "sp_host",
    "status": "published",
    "discard_reason": null,
    "created_at": "2026-10-28T10:00:00Z",
    "decided_at": "2026-10-28T11:00:00Z",
    "purge_after": "2027-01-26T11:00:00Z",
    "superseded_revision_id": null,
    "changes": {
      "sp_host": "login.example.com",
      "idp_entity_id": null,
      "idp_sso_url": null,
      "idp_slo_url": null,
      "certificate_fingerprints": [],
      "mfa_authn_context_values": null,
      "issuer": null,
      "client_id": null,
      "client_auth_method": null,
      "provider_profile": null,
      "client_secret_change": null
    },
    "latest_test": {
      "test_id": "conntest_01j9xr4a6b8c0d2e4f6g8h0j2k",
      "status": "passed",
      "failure_reason": null,
      "started_at": "2026-10-28T10:05:00Z",
      "completed_at": "2026-10-28T10:06:00Z"
    }
  },
  "already_published": false
}
```

## 오류

| HTTP | code | 발생 조건 |
|---|---|---|
| 400 | `unknown_field` | 본문이 비어 있지 않고 `{}`도 아닙니다. |
| 401 | `unauthenticated` | 자격 증명이 없거나, 유효하지 않거나, 취소되었습니다. |
| 403 | `insufficient_permissions` | 자격 증명에 `connections:write` 권한이 없습니다. |
| 404 | `not_found` | 이 환경에 연결 또는 리비전이 없거나, 리비전이 다른 연결에 속합니다. |
| 409 | `conflict` | 사전 조건이 충족되지 않습니다. `detail`에서 이유를 확인할 수 있습니다: 리비전이 폐기되었습니다. 최근 24시간 이내에 통과한 테스트가 없습니다. 초안을 만든 후 연결이 변경되었습니다(새 초안을 만드십시오). 이전 SP 호스트 마이그레이션의 30일 기간이 아직 끝나지 않았습니다. 새 SP 호스트가 더 이상 이 환경의 호스트가 아닙니다. 연결이 활성 서명 인증서 3개를 초과하게 됩니다. |
| 429 | `rate_limited` | 요청 한도를 초과했습니다. `Retry-After` 기간이 지난 후 다시 시도하십시오. |
| 503 | `service_unavailable` | 종속 서비스를 일시적으로 사용할 수 없습니다. `Retry-After` 기간이 지난 후 다시 시도하십시오. |

## 예제

```bash
curl -X POST "https://api.eu.keenauth.com/v1/connections/conn_01j9xp6q0r1s5t7v9w1x3y5z7b/revisions/connrev_01j9xr8c2d4e6f8g0h2j4k6m8n:publish" \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
```

```bash
keenauth connections revisions publish conn_01j9xp6q0r1s5t7v9w1x3y5z7b connrev_01j9xr8c2d4e6f8g0h2j4k6m8n --yes
```
