Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
a685b07
feat(sdk): publish scan findings through connected Linear app
kmbroai Aug 15, 2026
078966b
feat(sdk): prepare security findings for publication
kmbroai Aug 15, 2026
5e7b105
feat(sdk): stream scan publication progress events
kmbroai Aug 15, 2026
5ddd5dd
fix(sdk): use Luna low effort for Linear publication
kmbroai Aug 15, 2026
b0de228
feat(cli): add interactive scan publication to Linear
kmbroai Aug 15, 2026
c93bb0c
fix(cli): make scan publication choices easier to read
kmbroai Aug 15, 2026
6b78fe5
feat(cli): show live scan publication progress
kmbroai Aug 15, 2026
fa0fb0f
fix(sdk): recognize connected Linear issue creation results
kmbroai Aug 15, 2026
2f87bd4
feat(sdk): persist finding publication associations
kmbroai Aug 15, 2026
10ff541
fix(sdk): batch Linear issues with durable database-backed results
kmbroai Aug 15, 2026
62b240a
fix(cli): align published scan choices into columns
kmbroai Aug 15, 2026
b6cd5ff
fix(sdk): preserve sealed-file identity on Windows Node 22
kmbroai Aug 15, 2026
4822111
fix(sdk): avoid redundant upload identifiers in findings
kmbroai Aug 15, 2026
5bedb20
Merge commit '4822111' into dev/kyleb/linear-publish-engine
kmbroai Aug 15, 2026
a34f486
fix(sdk): recognize connected Linear issue creation results
kmbroai Aug 15, 2026
405b00d
feat(sdk): persist finding publication associations
kmbroai Aug 15, 2026
d71a863
feat(sdk): batch finding publication through durable database handoffs
kmbroai Aug 15, 2026
38caade
refactor(cli): isolate scan publication command and integration tests
kmbroai Aug 15, 2026
83aff49
fix(sdk): require concurrent Linear issue creation per batch
kmbroai Aug 15, 2026
274b719
Merge commit '83aff49' into HEAD
kmbroai Aug 15, 2026
94b8388
test(sdk): consolidate durable publication regressions
kmbroai Aug 15, 2026
2cb6e6b
test(sdk): consolidate connected Linear publication coverage
kmbroai Aug 15, 2026
5926306
merge: inherit focused publication engine tests
kmbroai Aug 15, 2026
69a2b72
merge: inherit focused publication parser coverage
kmbroai Aug 15, 2026
70b4201
merge: inherit focused durable publication tests
kmbroai Aug 15, 2026
72f6830
fix(sdk): match Linear publication results by finding identity
kmbroai Aug 15, 2026
8b9f2a6
Merge commit '72f683077af7831fa91d12b3d2732691b0048b6c' into HEAD
kmbroai Aug 15, 2026
a6f150f
Merge commit '8b9f2a61e51db2f2fa26cf5ca71bad866ee9ed03' into HEAD
kmbroai Aug 15, 2026
6e9fa3b
fix(sdk): reconcile publication handoffs by stable finding IDs
kmbroai Aug 15, 2026
c482c69
Merge commit '6e9fa3b0692494e2fd5e76ddb35b919effa886fa' into HEAD
kmbroai Aug 15, 2026
f0d54b3
fix(sdk): preserve full Linear issue descriptions during publication
kmbroai Aug 15, 2026
9c58e4c
Merge commit 'f0d54b3' into HEAD
kmbroai Aug 15, 2026
d80fd7b
test(cli): load durable publication arguments from prepared payload
kmbroai Aug 15, 2026
3906592
fix(sdk): preserve sealed-file identity on Windows Node 22
kmbroai Aug 15, 2026
aca4db5
fix(sdk): preserve partial Linear publications on cancellation
kmbroai Aug 15, 2026
8e1a4e2
fix(sdk): terminate Linear publication process trees on cancellation
kmbroai Aug 15, 2026
1b67824
Merge Linear publication cancellation support into persistence
kmbroai Aug 15, 2026
b335c58
Merge cancellable Codex process lifecycle into durable publication
kmbroai Aug 15, 2026
2f4e0f4
fix(cli): await Linear publication recovery after interruption
kmbroai Aug 15, 2026
d10a3cd
Merge durable cancellation and process-tree cleanup into publication CLI
kmbroai Aug 15, 2026
57c51bb
fix(sdk): preserve created Linear issues when receipt writes fail
kmbroai Aug 15, 2026
0235843
Merge verified Linear receipt warnings into publication persistence
kmbroai Aug 15, 2026
1126732
fix(sdk): report persisted Linear issues when receipts fail
kmbroai Aug 15, 2026
86384db
Merge verified receipt warnings into durable Linear publication
kmbroai Aug 15, 2026
c603e6b
fix(cli): skip unavailable scans and surface publication receipt warn…
kmbroai Aug 15, 2026
67f853c
Merge safe publication receipt warnings into scan publication CLI
kmbroai Aug 15, 2026
5b18c90
feat(publish): allow team-only Linear publication destinations
kmbroai Aug 15, 2026
a3d080b
feat(publish): support connected Linear team-only publication
kmbroai Aug 15, 2026
b2b7e92
Merge optional Linear destination contract into publication engine
kmbroai Aug 15, 2026
a86b22a
test(publish): keep optional destination assertions well typed
kmbroai Aug 15, 2026
0441a8e
feat(workbench): persist team-only Linear publications safely
kmbroai Aug 15, 2026
c384a92
Merge optional Linear publication contract into SQLite persistence
kmbroai Aug 15, 2026
df565a8
feat(publish): preserve team-only durable Linear handoffs
kmbroai Aug 15, 2026
444ed66
feat(cli): make Linear project selection optional
kmbroai Aug 15, 2026
39a9f89
Merge optional Linear destination persistence into durable publisher
kmbroai Aug 15, 2026
11c6ce5
Merge optional team-only publication into Linear CLI
kmbroai Aug 15, 2026
7975370
test(cli): type optional Linear project expectations precisely
kmbroai Aug 15, 2026
8ace470
fix(publish): preserve every sealed scan coverage mode
kmbroai Aug 16, 2026
2b67f38
Merge truthful sealed scan provenance into publication engine
kmbroai Aug 16, 2026
17797bb
Merge truthful sealed scan provenance into publication persistence
kmbroai Aug 16, 2026
61985a3
Merge truthful sealed scan provenance into durable publication
kmbroai Aug 16, 2026
4e1738a
Merge truthful sealed scan provenance into publication CLI
kmbroai Aug 16, 2026
8003667
Merge main after sealed publication foundation landed
kmbroai Aug 16, 2026
3e66ffc
Merge resolved main publication base into workbench persistence
kmbroai Aug 16, 2026
ec1421f
Merge resolved main publication base into durable publication
kmbroai Aug 16, 2026
02b6e7a
Merge resolved main publication base into Linear CLI
kmbroai Aug 16, 2026
15acebe
Merge main after connected publication engine landed
kmbroai Aug 16, 2026
f05d7a6
Merge landed publication engine into durable publisher ancestry
kmbroai Aug 16, 2026
5640adb
Merge landed publication engine into Linear CLI ancestry
kmbroai Aug 16, 2026
7edd09a
Merge main after publication persistence landed
kmbroai Aug 16, 2026
6e84467
Merge landed publication persistence into Linear CLI ancestry
kmbroai Aug 16, 2026
5f9623d
fix(sdk): preserve recoverable Linear publication outcomes
kmbroai Aug 16, 2026
b787e87
Merge Linear publication review fixes into CLI stack
kmbroai Aug 16, 2026
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
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,29 @@ root cause, reuses saved matches, and identifies new, persisting, reopened,
resolved, or unknown findings. Missing findings remain unknown when coverage is
incomplete or their original location was not reviewed.

## Publish scan findings

Publish every finding from a completed scan to a Linear team:

```bash
npx @openai/codex-security publish scan /path/to/scan \
--to linear \
--linear-team TEAM_ID
```

Add `--project PROJECT_ID` to place the issues in a Linear project, or omit it
to create issues directly in the team. Omit the scan directory to select a
completed scan interactively. You can also set `CODEX_SECURITY_LINEAR_TEAM` and
the optional `CODEX_SECURITY_LINEAR_PROJECT` instead of passing the destination
flags. Add `--dry-run` to preview the issues or `--json` to return
machine-readable results.

Publishing uses your existing Codex sign-in and connected Linear app; no
separate Linear token is required. Every finding creates a new issue containing
the scan ID, affected code locations, source snippets, and remediation guidance.
Choose a destination authorized to receive the repository's source code and
vulnerability details.

## Verbose diagnostics

Add `--verbose` to print scan diagnostics to stderr:
Expand Down
68 changes: 68 additions & 0 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ npx @openai/codex-security export
npx @openai/codex-security export /path/outside/repository/results --export-format sarif --output /path/outside/repository/results.sarif
npx @openai/codex-security export /path/outside/repository/results --export-format csv --output /path/outside/repository/findings.csv
npx @openai/codex-security export /path/outside/repository/results --export-format json --output /path/outside/repository/findings.json
npx @openai/codex-security publish scan /path/outside/repository/results --to linear --linear-team TEAM_ID
npx @openai/codex-security publish scan --to linear --linear-team TEAM_ID
npx @openai/codex-security validate /path/outside/repository/findings.json "Possible SQL injection in src/query.ts:42"
npx @openai/codex-security validate "Possible SQL injection" --effort high
npx @openai/codex-security patch /path/outside/repository/findings.json "Missing authorization check in src/routes.ts:18"
Expand Down Expand Up @@ -544,6 +546,72 @@ and scans stopped at their configured cost limit do not start another turn.
invocation and defaults to `1`. Results remain under `--output-dir`; rerun the
same command to resume.

### Publish completed scans to Linear

Publish every finding from a completed standard, deep, or scoped scan to one
Linear team:

```bash
npx @openai/codex-security publish scan /path/to/completed-scan \
--to linear \
--linear-team TEAM_ID
```

Add `--project PROJECT_ID` to place the issues in a Linear project. Without a
project, issues are created directly in the selected team.

To choose from all completed scans saved in your local scan history, omit the
scan directory:

```bash
npx @openai/codex-security publish scan \
--to linear \
--linear-team TEAM_ID
```

Destination flags take precedence over `CODEX_SECURITY_LINEAR_TEAM` and the
optional `CODEX_SECURITY_LINEAR_PROJECT`. Use `--dry-run` to preview the issue
titles without creating them, or `--json` to return structured publication
results.

Publishing starts Codex with your existing Codex configuration and connected
Linear app. Sign in to Codex and connect Linear before publishing. The command
does not require a Linear API token and does not use the isolated Codex home
created for security scans.

Each finding creates a separate new issue titled
`[Codex Security][HIGH] Finding title`. The issue includes the scan ID,
repository, scanned scope, source locations and code snippets, severity,
confidence, vulnerability classification, summary, and remediation guidance.
Verified immutable Git revisions include source links. Findings are published
concurrently in batches of up to 20. Successful issue identifiers are linked
to their findings in the local scan-history database, and structured results
are read back from that database rather than generated by Codex. The completed
scan must already exist in the local scan history. Running publication again
creates another set of issues for the same scan; existing issues are not
matched, updated, or reused.

Issue descriptions contain source code and vulnerability details. Select a
Linear destination authorized to receive that information. Publication receipts
are stored separately from the sealed scan artifacts.

You can also publish a scan from TypeScript:

```ts
import { publishScan } from "@openai/codex-security";

const publication = await publishScan("/path/to/completed-scan", {
destination: "linear",
teamId: "TEAM_ID",
});

console.log(publication.scanId);
console.log(publication.created.length);
```

Add `projectId: "PROJECT_ID"` to the options to publish into a specific Linear
project instead of directly to the team.

### Scan history and reruns

`scans` or `scans list` lists scans for the current repository. Pass a repository
Expand Down
49 changes: 48 additions & 1 deletion sdk/typescript/scripts/smoke-package.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import {
chmod,
cp,
mkdir,
mkdtemp,
readFile,
Expand Down Expand Up @@ -344,7 +346,7 @@ try {
[
"--input-type=module",
"--eval",
`const sdk = await import(${JSON.stringify(packageManifest.name)}); if (typeof sdk.CodexSecurity !== "function") throw new Error("The installed package does not export CodexSecurity.");`,
`const sdk = await import(${JSON.stringify(packageManifest.name)}); if (typeof sdk.CodexSecurity !== "function") throw new Error("The installed package does not export CodexSecurity."); if (typeof sdk.publishScan !== "function") throw new Error("The installed package does not export publishScan.");`,
],
{ cwd: consumer },
);
Expand Down Expand Up @@ -398,6 +400,51 @@ try {

const help = runInstalledCli("--help");
assert.match(help, /Usage: codex-security\b/u);
assert.match(help, /\bpublish\b/u);

const publicationScan = join(consumer, "publication-scan");
await cp(
join(installedRoot, "_bundled_plugin", "examples", "completed-scan"),
publicationScan,
{ recursive: true },
);
if (process.platform !== "win32") await chmod(publicationScan, 0o700);
const publication = JSON.parse(
run(
process.execPath,
[
launcher,
"publish",
"scan",
publicationScan,
"--to",
"linear",
"--linear-team",
"team-example",
"--dry-run",
"--json",
],
{
cwd: consumer,
capture: true,
env: {
...process.env,
CODEX_SECURITY_LINEAR_PROJECT: "",
CODEX_SECURITY_STATE_DIR: join(consumer, "publication-state"),
},
},
),
);
assert.equal(publication.scanId, "scan_example_001");
assert.equal(publication.uploadId, publication.scanId);
assert.deepEqual(publication.destination, {
type: "linear",
teamId: "team-example",
});
assert.equal(publication.dryRun, true);
assert.equal(publication.counts.findings, 1);
assert.equal(publication.counts.created, 0);
assert.match(publication.issues[0].title, /^\[Codex Security\]\[HIGH\] /u);

await smokeNestedDeepScanWorker(installedRoot, consumer);

Expand Down
Loading
Loading