From 0fe86ea3432fbc382cf94602f14510d774f36ce8 Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Sat, 1 Aug 2026 17:33:25 +1000 Subject: [PATCH 1/2] Add npm trusted-publishing workflow There is currently no CI publish path: main sits at tesla-fleet-api@0.2.1 with no way to ship it. Restores this repo's own pre-2024 convention (publish on GitHub Release published) using npm OIDC trusted publishing instead of a long-lived NPM_TOKEN secret, matching how the rest of the Teslemetry fleet publishes. --- .github/workflows/publish.yml | 39 +++++++++++++++++++++++++++++++++++ AGENTS.md | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9831ef0 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,39 @@ +name: Publish + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + publish: + name: Publish to npm + runs-on: ubuntu-latest + permissions: + id-token: write # npm OIDC trusted publishing - no NPM_TOKEN secret needed + steps: + - uses: actions/checkout@v4 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: "https://registry.npmjs.org" + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Upgrade npm for OIDC support + run: npm install -g npm@latest # trusted publishing needs npm >= 11.5.1 + + - name: Build + run: npx tsc + + - name: Publish to npm + run: npm publish --provenance --access public diff --git a/AGENTS.md b/AGENTS.md index 851c21c..69bca62 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ This file is the project's committed home for project-intrinsic agent knowledge: - For `DOMAIN_VEHICLE_SECURITY`, `Commands.dispatch` holds the domain's session lock across the *entire* dispatch (handshake + build + send + retry), not just message-build - VCSEC requires messages to arrive in strict counter order and the spec warns against simultaneous requests to it at all, unlike Infotainment (sliding window), which keeps the narrower build-only lock. - `Commands`'s `#privateKey`/`#publicKey` are native private class fields (not `protected`/TS-only `private`) - the raw signing key must not be reachable off the instance at all (e.g. via `JSON.stringify` or a structured log), not merely inaccessible to outside *code*. Tests that need to observe key derivation do so through what actually goes out on the wire (a captured handshake message), not by reading the field. - `src/tariff.ts`'s `getTariffPeriods(tariff, now, opts)` is a pure Tariff V2 rate resolver mirroring `python-tesla-fleet-api`'s sibling. The tariff object carries no timezone; the caller must pass `opts.timeZone` (an IANA string, e.g. from `site_info.installation_time_zone`) - the resolver has no other way to get site-local wall-clock parts from a JS `Date`, which is always a UTC instant. It resolves one calendar day at a time (`dayPeriods`), not a multi-day minute-of-week span, because a `tou_periods` entry's `fromDayOfWeek..toDayOfWeek` means "this daily time window recurs on each of these weekdays", not "one span from this day+time to that day+time"; `nextChange`/`upcoming` re-resolve the season fresh on each day so a horizon crossing a season boundary re-prices correctly, and a gap between scheduled periods reports the gap (not the next period found arbitrarily far out). Converting a resolved wall-clock boundary back to a `Date` goes through `wallClockToUtcMillis` (iterative, since the zone's UTC offset at the target instant is what's being solved for) rather than adding elapsed real minutes to `now` - the two diverge across a DST transition. The reverse direction - "what calendar day/weekday is N minutes of wall-clock time from now" (used to walk forward day by day, or peek at tomorrow) - must go through `wallClockAt` (pure calendar arithmetic, no `Intl` round trip), never `now.getTime() + minutes*60000`; the latter silently lands on the wrong calendar day on a DST fall-back day (25 real hours) or spring-forward day (23). Buy and sell resolve independently via `scheduleAt`, which reports both a `nextChangeGM` and a `sinceGM` even for a grid currently sitting in a gap (e.g. a sell/export window not open yet, or already closed) - `nextChange` (earlier of the two) and `currentStart` (later of the two) must fold in the sell side even when sell has no period active right now, or a differently-scheduled sell tariff gets silently ignored or backdated. Both are nullable (bounded to one day of lookahead/lookback, mirroring each other) and must be excluded from the combination via `!= null`, not treated as `0`, when a grid has nothing scheduled in that window at all. `TariffContentV2` (`src/types/site_info.ts`) types `seasons` as `Record` (an object keyed by season name, not an array) - that mismatch was a real bug fixed alongside the resolver; don't regress it back to an array shape. -- There is no CI publish path: `.github/workflows/` has only `ci.yml` (typecheck + test on push/PR); a `publish.yaml` (npm publish on GitHub Release) existed briefly in 2024 and was deleted. Publishing a new version to npm is a manual `npm publish` by someone with registry credentials/2FA for the `tesla-fleet-api` package - a version bump landing on `main` does not by itself ship anything to npm. Before assuming a version is live, check `npm view tesla-fleet-api@` rather than trusting `package.json`. +- `.github/workflows/publish.yml` publishes to npm on GitHub Release `published` (matching this repo's own pre-2024 convention, restored) via npm trusted publishing (OIDC) - `id-token: write`, no `NPM_TOKEN` secret. It builds with `npx tsc` before `npm publish --provenance`, so a version bump landing on `main` still ships nothing by itself; publishing happens only when a GitHub Release is cut for that tag, and only once trusted publishing is enabled on the npm package side for this repo/workflow. Before assuming a version is live, check `npm view tesla-fleet-api@` rather than trusting `package.json`. ## Maintaining this file From 0ed5a934dd33bf92f315e71b3b89fca37ba6b93c Mon Sep 17 00:00:00 2001 From: Brett Adams Date: Sat, 1 Aug 2026 17:36:37 +1000 Subject: [PATCH 2/2] no-mistakes(review): Add checkout permission to publish job --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9831ef0..4d4837c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,6 +12,7 @@ jobs: name: Publish to npm runs-on: ubuntu-latest permissions: + contents: read id-token: write # npm OIDC trusted publishing - no NPM_TOKEN secret needed steps: - uses: actions/checkout@v4