Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ generator owns the code you are changing, preserve existing generated behavior,
authoritative source when it is available. The `openai-java-example/` directory is not modified by
the generator.

## Custom-code budget
<a id="custom-code-budget"></a>

Follow [the custom-code guidance](scripts/castiron/CUSTOM_CODE.md). Budget changes
belong in a separate PR containing only `.castiron-ratchet.json`, with an explicit justification
in the PR description. Increases require a **human approving review** before merging.
Agents may investigate and draft proposals, but must not approve budget increases
(including through a human's credentials) or bypass the gate. Do not weaken
counting, broaden exclusions, or alter generation metadata to make a change pass.
The checker and effective budget come from main, not the PR. Keep default CODEOWNERS.
## Generated-file ownership

Never hand-edit generated SDK files, including generated tests, documentation,
workflows, or the generated-file inventory. Change the authoritative API schema,
configuration, or compiler, then regenerate. Put SDK-specific behavior in
separately owned handwritten helpers and extension points.

Regeneration replaces generator-owned files and deletes retired generated paths.
Handwritten edits to generated files are overwritten; they are never replayed or
merged into new output. Preserve separately owned handwritten files and resolve
ownership collisions explicitly. Follow this AGENTS.md rule and review generated output and inventory changes
together. The simplified workflow relies on contributor guidance and code review.
This intermediate revision retains the legacy strict generated-file checker,
which rejects manifest mismatches when invoked. Respect retained checks and any
currently required statuses until canonical regeneration removes the tooling.
Fix violations in the inputs/compiler and regenerate; never update inventory
hashes to accept a handwritten patch.

## Security requirements

Expand Down
45 changes: 27 additions & 18 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,31 @@ management. The framework-neutral SDK requires Java 8, while development require
Kotlin toolchain. See the [Java version support policy](docs/version-support-policy.md) for
artifact-level runtime, framework, lifecycle, and release rules.

## Custom-code budget

The custom-code budget counts additions plus deletions in the remaining patch
against verified generated output. `.castiron-ratchet.json` defines this repository's
ceiling. CI uses the checker and budget on main, not the PR's proposed versions.

Budget changes must be in a separate PR modifying **only `.castiron-ratchet.json`**.
Justify the current usage, proposed ceiling, and why fixing generation is not
appropriate in the PR description. Increases require a **human approving review**
and must merge before an SDK change relies on them. Agents may draft proposals,
but must not approve increases or bypass the gate. Keep default CODEOWNERS.
Lower the ceiling after cleanup while retaining headroom; decreases must still
fit the measured usage.

See [custom-code technical details](scripts/castiron/CUSTOM_CODE.md) for accounting,
local checks, trusted CI, and activation instructions.
<a id="custom-code-budget"></a>

## Generated-file ownership

Do not edit generated SDK files by hand. Fix the API schema, generation
Comment thread
jbeckwith-oai marked this conversation as resolved.
Resolved
configuration, or compiler and regenerate instead. Put SDK-specific behavior in
separately owned handwritten helpers and extension points.

Regeneration replaces generated files and removes retired generated paths.
Handwritten edits to generated output are overwritten, not carried forward.
Separately owned handwritten files are preserved. Resolve ownership conflicts
explicitly before regeneration. Follow the ownership rules in `AGENTS.md`
and review generated output and inventory changes together. Generated-file
ownership under the simplified workflow relies on contributor guidance and code
review. This revision still contains the legacy strict generated-file checker,
which rejects manifest mismatches when invoked; inspect live workflow settings
and required statuses separately until canonical regeneration removes it. Fix violations in the
generation inputs/compiler and regenerate; do not edit inventory hashes to
accept a handwritten patch.

This `next` guidance precedes canonical regeneration: the legacy reporting
workflow definitions and tools still exist in this revision. Preserve their
security checks until removal, and inspect actual workflow settings and results
rather than assuming this document disables them. Do not start new budget
changes or bypass required checks.
Comment thread
jbeckwith-oai marked this conversation as resolved.
Resolved

## Security expectations

Expand Down Expand Up @@ -90,8 +99,8 @@ artifact's eligibility on a given JVM come from `gradle/version-support.properti

## Modifying or adding code

Most of the SDK is generated code. Modifications to code will be persisted between generations, but may
result in merge conflicts between manual patches and changes from the generator. The generator will never
Most of the SDK is generated code. Never edit generated files by hand; change
the authoritative generation inputs or compiler and regenerate instead. The generator will never
modify the contents of the `openai-java-example/` directory.

## Adding and running examples
Expand Down
22 changes: 16 additions & 6 deletions docs/architecture/security-model.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# OpenAI Java SDK security model

Generated files are updated through authoritative inputs or the compiler and
regeneration; handwritten edits to them are forbidden. Code review enforces this
ownership rule. This `next` revision still contains the legacy budget/reporting
workflows and publisher code pending separate canonical regeneration. This
change does not remove or disable those workflows. Until removal, preserve and
review their trusted-code, artifact-validation, event/repository/revision,
freshness, and least-privilege boundaries. Their historical protocol is documented
in `scripts/castiron/CUSTOM_CODE.md`; it does not authorize new generated-file
patches or a replacement budget system.

This is the repository's single canonical detailed threat model. Use it for
security review and Codex Security scans of the revision being reviewed.
SECURITY.md remains the authority for private disclosure and reportability
Expand All @@ -20,10 +30,10 @@ repository.

| Component | Purpose and important flow | Evidence |
| --- | --- | --- |
| openai-java-core | Transport-neutral client, generated services and models, request construction, authentication headers, retry/logging wrappers, JSON/SSE parsing, and webhook verification. | CONTRIBUTING.md:69-72; openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt:57-140; openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt:747-808 |
| openai-java-client-okhttp | Default HTTP transport, caller-configurable proxy, redirects, timeouts, TLS, and hostname verification. | CONTRIBUTING.md:73-75; openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt:54-65; openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OkHttpClient.kt:180-242 |
| openai-java | Umbrella artifact exposing core and OkHttp APIs without its own logic. | CONTRIBUTING.md:76-78; openai-java/build.gradle.kts:1-8 |
| openai-java-bedrock | Optional Bedrock endpoint selection and bearer or AWS SigV4 authentication. | CONTRIBUTING.md:79-80; openai-java-bedrock/src/main/kotlin/com/openai/bedrock/BedrockAuth.kt:64-215 |
| openai-java-core | Transport-neutral client, generated services and models, request construction, authentication headers, retry/logging wrappers, JSON/SSE parsing, and webhook verification. | CONTRIBUTING.md:78-81; openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt:57-140; openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt:747-808 |
| openai-java-client-okhttp | Default HTTP transport, caller-configurable proxy, redirects, timeouts, TLS, and hostname verification. | CONTRIBUTING.md:82-84; openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt:54-65; openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OkHttpClient.kt:180-242 |
| openai-java | Umbrella artifact exposing core and OkHttp APIs without its own logic. | CONTRIBUTING.md:85-87; openai-java/build.gradle.kts:1-8 |
| openai-java-bedrock | Optional Bedrock endpoint selection and bearer or AWS SigV4 authentication. | CONTRIBUTING.md:88-89; openai-java-bedrock/src/main/kotlin/com/openai/bedrock/BedrockAuth.kt:64-215 |
| openai-java-vertex | Optional Vertex endpoint selection and Google bearer authentication. | openai-java-vertex/README.md; openai-java-vertex/src/main/kotlin/com/openai/client/okhttp/VertexOpenAIOkHttpClient.kt |
| Build and release workflows | Unprivileged PR validation and separately gated main-only release/publish jobs. | .github/workflows/ci.yml:3-24; .github/workflows/create-releases.yml:3-25 |

Expand Down Expand Up @@ -79,7 +89,7 @@ not exposed to the attestation action.
application's responsibility.
- Large JSON bodies and streaming events are supported API contracts. Reviews
should prefer incremental processing, cleanup, and cancellation; a large
payload is not by itself hostile or malformed. (AGENTS.md:49-66)
payload is not by itself hostile or malformed. (AGENTS.md:59-76)
- Main-branch integrity, protected release credentials, GPG signing material,
OIDC attestation authority, artifact/source binding, and Gradle cache isolation
must remain unreachable from unmerged PR code.
Expand Down Expand Up @@ -169,7 +179,7 @@ These are review hypotheses, not confirmed findings.
| --- | --- | --- | --- | --- | --- | --- |
| High | PR-controlled code reaches protected release credentials or signing/attestation authority before merge/release governance. | A workflow trigger, checkout ref, artifact restore, or environment gate is weakened. | Credential theft or forged official artifacts. | Release is main/schedule/manual only, selects/verifies source, gates runtime compatibility, uses protected publish, and disables release cache reuse. | Preserve source binding, least permissions, environment protection, and no PR artifact/cache import. | .github/workflows/create-releases.yml:3-25; .github/workflows/create-releases.yml:90-164; .github/workflows/create-releases.yml:241-290; .github/workflows/create-releases.yml:426-469 |
| High | Untrusted webhook bytes are parsed or acted on without valid signature/freshness checks. | Embedding application exposes webhook ingress and relies on SDK verification. | Forged event acceptance. | Required headers, bounded timestamp tolerance, HMAC-SHA256, timing-safe compare, then parse; no replay deduplication. | Preserve verify-before-parse ordering and focused regression tests; embedding applications must deduplicate accepted webhook IDs when replay matters. | openai-java-core/src/main/kotlin/com/openai/services/WebhookVerification.kt:19-99; openai-java-core/src/main/kotlin/com/openai/services/blocking/WebhookServiceImpl.kt:33-41 |
| Medium | Independently mutable API/SSE JSON crosses a parser boundary and causes unsafe interpretation, resource exhaustion, or sensitive exception/log output. | Attacker controls an API/network response or configured proxy; sink is reachable in caller deployment. | Client failure, data exposure, or downstream misuse. | Strict mapper defaults, typed parsing, stream iteration, and explicit DEBUG diagnostics. | Keep parsing robust and large-payload-compatible; avoid treating model output as executable authority without caller controls. | openai-java-core/src/main/kotlin/com/openai/core/ObjectMappers.kt:34-116; openai-java-core/src/main/kotlin/com/openai/core/handlers/SseHandler.kt:19-60; AGENTS.md:49-66 |
| Medium | Independently mutable API/SSE JSON crosses a parser boundary and causes unsafe interpretation, resource exhaustion, or sensitive exception/log output. | Attacker controls an API/network response or configured proxy; sink is reachable in caller deployment. | Client failure, data exposure, or downstream misuse. | Strict mapper defaults, typed parsing, stream iteration, and explicit DEBUG diagnostics. | Keep parsing robust and large-payload-compatible; avoid treating model output as executable authority without caller controls. | openai-java-core/src/main/kotlin/com/openai/core/ObjectMappers.kt:34-116; openai-java-core/src/main/kotlin/com/openai/core/handlers/SseHandler.kt:19-60; AGENTS.md:59-76 |
| Medium | Credentials or customer payloads reach an unintended destination or uncontrolled log. | Lower-trust actor independently controls base URL/proxy/TLS/log sink, or diagnostics are enabled in an unsafe deployment. | Secret or customer-data disclosure. | Production URL default, caller-owned configuration, auth wrappers, and default sensitive-header redaction; DEBUG is explicit. | Preserve redaction and destination/TLS controls; document caller obligations. | openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt:151-172; openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt:601-665; openai-java-core/src/main/kotlin/com/openai/core/http/LoggingHttpClient.kt:24-48; openai-java-core/src/main/kotlin/com/openai/core/http/LoggingHttpClient.kt:91-142 |
| Medium | A separately privileged evaluator consumes mutable PR Git objects, artifacts, or cache entries as trusted code/data. | Privileged workflow reads candidate state without binding/ref validation. | Privilege crossing beyond ordinary PR CI. | Custom-code workflow checks out main, uses current PR objects, and freshness-checks exact head; PR cache scope remains isolated. | Preserve trusted checkout and exact-head/digest binding. | .github/workflows/castiron-custom-code-comment.yml:34-57; .github/workflows/castiron-custom-code-comment.yml:128-181; .github/workflows/ci.yml:120-129 |
| Low / not a boundary by itself | A PR changes a checked-in example, test, fixture, build script, or generated source and ordinary PR CI executes it. | The same PR author already controls the tracked executable checkout. | No new capability beyond the unprivileged PR job. | PR CI has read-only contents and no release credentials; cache scope is enforced outside PR code. | Investigate only if execution crosses an independent input or protected-authority boundary. | .github/workflows/ci.yml:8-20; .github/workflows/ci.yml:33-48; .github/workflows/ci.yml:92-107 |
Expand Down
Loading