Skip to content

Commit c0934cc

Browse files
committed
fix: harden options and publication contracts
1 parent 66c8a80 commit c0934cc

22 files changed

Lines changed: 1035 additions & 171 deletions

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ body:
1212
id: version
1313
attributes:
1414
label: CometAPI SDK version
15-
placeholder: 0.1.0-alpha.1
15+
description: Run `npm list cometapi` and report the installed package version.
16+
placeholder: Paste the installed package version
1617
validations:
1718
required: true
1819
- type: input

AGENTS.md

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ repository.
5151
merely to complete lifecycle cleanup. Fail closed and report the exact state
5252
whenever a required cleanliness, fetch, or fast-forward condition is not met.
5353

54-
## Current Milestone: Stable 0.1.1 and Repository Foundation Complete
54+
## Current Milestone: Stable 0.1.x Maintenance
5555

56-
Private Remote Validation, Public Preview, Registry Alpha, stable `0.1.0`, and
57-
the `0.1.1` maintenance patch are complete. The canonical repository is public,
58-
`0.1.1` is available from npm's `latest` channel, and `0.1.0-alpha.3` remains
59-
available from `next`; the published lines have verified provenance and
60-
public-install evidence. No later milestone is active. Do not begin the 0.2
61-
provider adapters without an explicit maintainer request.
56+
Private Remote Validation, Public Preview, Registry Alpha, and Repository
57+
foundation are complete. The canonical repository is public and remains in
58+
stable 0.1.x maintenance: stable packages use npm's `latest` channel and
59+
Registry Alpha artifacts use `next`. Do not pin an exact current package or
60+
Release version in durable repository guidance. Query npm and GitHub when exact
61+
state matters. No later milestone is active; do not begin the 0.2 provider
62+
adapters without an explicit maintainer request.
6263

6364
The accepted identity is:
6465

@@ -78,21 +79,23 @@ The unscoped `cometapi` package is the primary Node SDK. `@cometapi` is the
7879
standard scope for future official scoped packages; do not introduce new
7980
official packages under `@cometapi-dev`.
8081

81-
Stable `0.1.1` corrected the public options boundary without expanding the 0.1
82-
resource surface. Release Please created the reviewed patch PR, immutable tag,
83-
and GitHub Release. Publication required a disclosed one-time main-context
84-
recovery because the immutable tag predated the repaired tag handoff. The
85-
recovery published only the exact previously verified artifact through npm
86-
OIDC, then the repository restored its variables and tag-only Environment
87-
policy. The current workflow contains no publication-recovery input, fixed
88-
recovery run or artifact ID, prior-package-artifact or live-evidence reuse, or
89-
branch-context publication path.
82+
Stable `0.1.1` established the runtime options boundary and repaired the release
83+
path without expanding the 0.1 resource surface. Release Please created the
84+
reviewed patch PR, immutable tag, and GitHub Release. Publication required a
85+
disclosed one-time main-context recovery because the immutable tag predated the
86+
repaired tag handoff. The recovery published only the exact previously verified
87+
artifact through npm OIDC, then the repository restored its variables and
88+
tag-only Environment policy. The current workflow contains no
89+
publication-recovery input, fixed recovery run or artifact ID,
90+
prior-package-artifact or live-evidence reuse, or branch-context publication
91+
path.
9092

9193
Release Please remains disabled between explicitly authorized release
9294
operations. Permanent stable patches follow only the tag-bound path in
93-
`RELEASING.md`. The `0.1.1` recovery provenance is historical evidence, not
94-
proof that the current permanent tag path has completed a registry publication;
95-
the next explicitly authorized stable patch is its first end-to-end execution.
95+
`RELEASING.md`. The recovery provenance for stable `0.1.1` is historical
96+
evidence and does not prove an execution of the permanent path. The next
97+
explicitly authorized stable patch is that path's first end-to-end registry
98+
execution.
9699

97100
## Product Contract
98101

@@ -125,6 +128,11 @@ message translation are not 0.1 features.
125128
Do not hand-write replacements for those layers.
126129
- Use only documented public OpenAI constructor and client options. Do not
127130
depend on private upstream attributes or methods.
131+
- Declare CometAPI-owned `provider`, `workloadIdentity`, and
132+
`dangerouslyAllowBrowser` fields as optional `never` properties on
133+
`CometAPIOptions`. The constructor and `withOptions` must reject every
134+
non-`undefined` value at runtime as well as through TypeScript variables,
135+
spreads, and constrained generics.
128136
- Preserve official OpenAI request, response, stream, and exception types for
129137
the supported 0.1 operations.
130138
- Keep CometAPI-specific resources in `src/resources/` and their types in
@@ -243,6 +251,10 @@ repository root.
243251
- Inspect `npm pack` output, install the exact tarball in clean ESM, CommonJS,
244252
and compatible-OpenAI host fixtures, and verify version agreement before
245253
publication.
254+
- Treat `package.json` as the sole candidate-version authority. A normal stable
255+
Release Please PR changes exactly `.release-please-manifest.json`,
256+
`CHANGELOG.md`, `package-lock.json`, and `package.json`; all four version
257+
records must agree, while durable documentation remains publication-neutral.
246258
- Keep development checks compatible with unresolved maintainer input, but
247259
make the publish workflow fail closed until maintainers have supplied the
248260
copyright holder, canonical security and support contacts, repository

ARCHITECTURE.md

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ only for CometAPI defaults and public branding:
2929
3. The default base URL is `https://api.cometapi.com/v1`.
3030
4. Other documented and supported OpenAI client options pass through unchanged.
3131

32-
The public `CometAPIOptions` type excludes the upstream `provider`,
33-
`workloadIdentity`, and `dangerouslyAllowBrowser` fields in addition to the
34-
CometAPI-owned `apiKey` and `baseURL` fields. Provider and workload-identity
35-
routing conflict with the API key and base URL that this client injects.
36-
Browser-side long-lived key use is outside the 0.1 security boundary. These
37-
fields never represented valid CometAPI behavior, so their removal from the
38-
public type is a 0.1.1 contract correction rather than a supported feature
39-
removal.
32+
The public `CometAPIOptions` type omits the upstream definitions of `provider`,
33+
`workloadIdentity`, and `dangerouslyAllowBrowser`, then redeclares those names as
34+
`provider?: never`, `workloadIdentity?: never`, and
35+
`dangerouslyAllowBrowser?: never`. Provider and workload-identity routing
36+
conflict with the API key and base URL that this client injects. Browser-side
37+
long-lived key use is outside the 0.1 security boundary. The optional-`never`
38+
contract makes variables, spreads, and constrained generics structurally
39+
incompatible when they carry a non-`undefined` reserved value. These fields
40+
never represented valid CometAPI behavior, so tightening the declaration within
41+
stable 0.1.x is not a supported feature removal.
4042

4143
The inherited `withOptions` path is constrained to the same
4244
`CometAPIOptions` contract. Both the constructor and `withOptions` validate
@@ -99,15 +101,22 @@ The package manifest declares only intended runtime files. Generated build
99101
artifacts and dependency directories are not committed. A successful source-tree
100102
import is not package evidence; verification must use the packed artifact.
101103

102-
`package.json` is the source of the candidate version. Local and release checks
103-
derive the version from it and require agreement with the package-lock root,
104-
the Release Please manifest or the documented one-time bootstrap, the single
105-
candidate changelog heading, and packed metadata. Remote publication adds exact
106-
tag and GitHub release agreement.
104+
`package.json` is the sole source of the candidate version. Local and release
105+
checks derive the version from it and require agreement with the package-lock
106+
root, the Release Please manifest or the documented one-time bootstrap, the
107+
single candidate changelog heading, and packed metadata. A normal stable
108+
Release Please PR changes exactly `.release-please-manifest.json`,
109+
`CHANGELOG.md`, `package-lock.json`, and `package.json`; version-specific status
110+
does not belong in its durable documentation. Remote publication adds exact tag
111+
and GitHub Release agreement.
107112

108113
The publish workflow is the sole source of npm dist-tag selection: prereleases
109114
use `next`, stable versions use `latest`. The package manifest must not carry a
110115
static dist-tag because that would make stable and prerelease policy diverge.
116+
Exact registry and Release state must be queried from npm and GitHub rather than
117+
inferred from repository prose. The unversioned package page is
118+
<https://www.npmjs.com/package/cometapi>, and GitHub release state is available
119+
from <https://github.com/cometapi-dev/cometapi-node/releases>.
111120
Trusted Publishing is the only executable authentication path. The protected-
112121
environment token bootstrap used for `0.1.0-alpha.1` is historical evidence;
113122
current workflows contain no token publication path and reject registry-token

COMPATIBILITY.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
Compatibility document version: 0.1
44
Package line: `0.1.x`
55

6-
Stable release: `0.1.1`; the immutable Release, bounded live smoke, npm OIDC
7-
publication, and separate public-registry verification completed on 2026-07-30.
8-
Registry Alpha `0.1.0-alpha.3` remains available from npm's `next` channel.
6+
Maintenance status: stable `0.1.x`. Stable packages use npm's `latest` channel,
7+
and Registry Alpha artifacts use `next`. Exact package, dist-tag, and GitHub
8+
Release state is intentionally not pinned here; query
9+
<https://www.npmjs.com/package/cometapi> and
10+
<https://github.com/cometapi-dev/cometapi-node/releases>. Dated evidence for
11+
each completed release remains below.
912

1013
This matrix defines the contract-tested 0.1 compatibility surface. Inheritance
1114
from the official OpenAI client does not by itself establish CometAPI support.
@@ -42,24 +45,27 @@ error contract.
4245

4346
The 0.1 client keeps supported OpenAI transport and observability options, while
4447
reserving CometAPI routing, authentication, and the browser security boundary.
45-
The 0.1.0 declarations mistakenly admitted the three reserved fields even
46-
though they could not produce valid, supported CometAPI behavior; 0.1.1 corrects
47-
that contract:
48+
Earlier stable declarations omitted the three reserved fields, which rejected
49+
fresh object literals but still admitted structurally typed variables. Those
50+
fields never produced valid, supported CometAPI behavior. Stable maintenance
51+
therefore makes the prohibition structural:
4852

4953
| Option group | Contract |
5054
| -------------------------------------------------------------------------------------------- | -------------------------------------------- |
5155
| `timeout`, `maxRetries`, `fetch`, `fetchOptions`, `defaultHeaders`, `defaultQuery`, `logger` | Supported constructor pass-through |
5256
| `organization`, `project`, `webhookSecret`, `adminAPIKey` | Supported constructor pass-through |
5357
| Per-request options | Supported for the contract-tested operations |
54-
| `provider`, `workloadIdentity`, `dangerouslyAllowBrowser` | Rejected by declarations and at runtime |
58+
| `provider?: never`, `workloadIdentity?: never`, `dangerouslyAllowBrowser?: never` | Rejected by declarations and at runtime |
5559

5660
`provider` and `workloadIdentity` would conflict with the CometAPI API key and
5761
base URL injected by the SDK. `dangerouslyAllowBrowser` would cross the 0.1
58-
long-lived-key boundary. The constructor and `withOptions` enforce the same
59-
rule. Runtime rejections use the official OpenAI `OpenAIError`, identify only
60-
the forbidden field, and do not include its value. Compile-time negative tests
61-
are executed by TypeScript against source and packed ESM/CommonJS declarations;
62-
runtime tests cover plain JavaScript and type-cast bypasses.
62+
long-lived-key boundary. Redeclaring all three fields as optional `never` makes
63+
non-`undefined` values incompatible through object literals, inferred
64+
variables, spreads, and constrained generics. The constructor and `withOptions`
65+
enforce the same rule at runtime. Runtime rejections use the official OpenAI
66+
`OpenAIError`, identify only the forbidden field, and do not include its value.
67+
Compile-time negative tests run against source and packed ESM/CommonJS
68+
declarations; runtime tests cover plain JavaScript and type-cast bypasses.
6369

6470
## Inherited but unsupported in 0.1
6571

README.md

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ The official CometAPI entry point for the OpenAI-compatible API. The SDK keeps
44
the official OpenAI JavaScript request, response, stream, and error types while
55
defaulting the client to CometAPI.
66

7-
> **Stable 0.1 release:** `0.1.1` is published on npm's default `latest`
8-
> dist-tag. Its immutable GitHub Release, bounded live smoke, npm OIDC
9-
> publication, provenance, signature, and separate public-registry installation
10-
> verification are complete. The supported API remains limited to the
11-
> contract-tested 0.1 surface documented here and in
7+
> **Stable 0.1.x maintenance:** Stable packages install from npm's default
8+
> `latest` dist-tag, while prerelease artifacts use `next`. Exact package,
9+
> dist-tag, and GitHub Release state is intentionally not pinned in this README;
10+
> query the registries when that state matters. The supported API remains
11+
> limited to the contract-tested 0.1 surface documented here and in
1212
> [COMPATIBILITY.md](./COMPATIBILITY.md).
1313
1414
## Supported 0.1 surface
@@ -46,6 +46,17 @@ Install the stable package from npm's default `latest` dist-tag:
4646
npm install cometapi
4747
```
4848

49+
The unversioned registry page is
50+
<https://www.npmjs.com/package/cometapi>. Query npm and GitHub instead of using
51+
an exact version copied from repository prose:
52+
53+
```bash
54+
npm view cometapi version
55+
npm view cometapi dist-tags --json
56+
gh release view --repo cometapi-dev/cometapi-node \
57+
--json tagName,isDraft,isPrerelease,publishedAt,url
58+
```
59+
4960
The release workflow is the sole source of the npm dist-tag: prerelease
5061
versions publish to `next`, while stable versions publish to `latest`. The
5162
package manifest does not declare a static dist-tag.
@@ -164,12 +175,13 @@ const response = await client.chat.completions.create(
164175
);
165176
```
166177
167-
Starting with 0.1.1, the public type matches the runtime boundary that 0.1.0
168-
intended. The SDK owns CometAPI routing, authentication, and the Node-only
169-
secret boundary. Consequently, `provider`, `workloadIdentity`, and
170-
`dangerouslyAllowBrowser` are not `CometAPIOptions`. They are rejected both by
171-
the TypeScript declarations and at runtime when plain JavaScript or a type cast
172-
bypasses those declarations. The same restriction applies to inherited
178+
The 0.1.x public type matches the enforced runtime boundary. The SDK owns
179+
CometAPI routing, authentication, and the Node-only secret boundary.
180+
`CometAPIOptions` therefore declares `provider?: never`,
181+
`workloadIdentity?: never`, and `dangerouslyAllowBrowser?: never`. Non-`undefined`
182+
values are rejected by TypeScript, including through inferred variables,
183+
spreads, and constrained generics, and runtime validation protects plain
184+
JavaScript and type-cast bypasses. The same restriction applies to inherited
173185
`withOptions` calls. A rejection is an official OpenAI `OpenAIError` and names
174186
only the forbidden field; it never includes the supplied value.
175187
@@ -229,24 +241,20 @@ parent.
229241
230242
## Project status
231243
232-
The repository has completed Public Preview, Registry Alpha, stable `0.1.0`,
233-
the `0.1.1` maintenance patch, and Repository foundation. Blocking CI,
234-
protected repository rules, security reporting, protected environments, and
235-
the authorized bounded live smoke have passed. Stable `0.1.1` is available from
236-
`latest`; Registry Alpha `0.1.0-alpha.3` remains available from `next`. A
237-
separate public-registry check passed ESM, CommonJS, declarations, supported
238-
mocked calls, the compatible-OpenAI host fixture with one effective OpenAI
239-
installation, official error identity, integrity, signature, and provenance.
240-
241-
The immutable `0.1.0-alpha.2` GitHub release remains as an unpublished failure
242-
record because its guard stopped before invoking npm. Mocked responses, packed
243-
artifacts, GitHub Actions, trusted live tests, and npm publication remain
244-
separate evidence layers and must not be represented as another. Published npm
245-
artifacts are immutable, so the `0.1.1` tarball retains its candidate-era
246-
README; this post-release status first ships in a later package version. The
247-
one-time `0.1.1` publication recovery is documented as historical evidence in
248-
[RELEASING.md](./RELEASING.md); the current permanent release workflow is
249-
immutable-tag-bound. No 0.2 provider adapter work is included.
244+
The repository is in stable 0.1.x maintenance, and no 0.2 provider-adapter
245+
milestone is active. Repository foundation, Public Preview, and Registry Alpha
246+
are complete. Stable packages use `latest`; Registry Alpha artifacts use
247+
`next`. Use the npm and GitHub queries in [Installation](#installation) for
248+
exact current state. Release-specific CI, live-smoke, registry, integrity,
249+
signature, provenance, and public-install evidence is retained in
250+
[RELEASING.md](./RELEASING.md), not restated as mutable version status here.
251+
252+
Mocked responses, packed artifacts, GitHub Actions, trusted live tests, and npm
253+
publication remain separate evidence layers and must not be represented as one
254+
another. Exact failed-release, immutable-artifact, and one-time recovery history
255+
is retained in [RELEASING.md](./RELEASING.md) rather than reproduced in this
256+
consumer README. The permanent release workflow is immutable-tag-bound and
257+
publishes through npm OIDC.
250258
251259
See:
252260

0 commit comments

Comments
 (0)