Skip to content

[Release] Google v13 pin and clean-install certification #20

Description

@karlwaldman

Outcome

Certify and release the current Google Sheets runtime through one controlled immutable Apps Script version, preserve the working version 11 rollback, and obtain a clean-account published-artifact install/formula receipt. This is the single canonical tracker for Google OAuth, Marketplace version selection, installed-account certification, and the missing clean-account identity. Do not open parallel release/OAuth/Marketplace tickets.

Owner: @karlwaldman

Verified production state - 2026-08-11

  • Public Marketplace listing: https://workspace.google.com/marketplace/app/oilpriceapi_for_google_sheets/991152473434
  • Google Cloud project/app ID: oilpriceapi-sheets-addon / 991152473434.
  • Production Apps Script project: 1rlVWvciYu-wzqnY009I3oW-08ZPazYK1snrrMg9NNY7c5WBSkUK8W2Hb.
  • Marketplace App Configuration is Public and references immutable Apps Script version 11.
  • Public runtime represented by version 11: 1.2.2.
  • Google Auth Platform currently reports: Your app has been verified by Google.
  • Marketplace/OAuth scope parity is current: default userinfo.email and userinfo.profile, plus the only three functional scopes spreadsheets.currentonly, script.external_request, and script.container.ui.
  • Immutable version 12 contains runtime 1.3.0, failed later credential/cache-isolation review, and was never selected for the public listing.
  • Current repository release candidate: runtime 1.3.1, main 5eb7121c80c90279b2c08f4c231db18161b30958.
  • Workflow hardening PR ci: harden Sheets release workflows #34 changed only CI/test dependencies and merged as 5eb7121c80c90279b2c08f4c231db18161b30958; the four Apps Script runtime files remain byte-identical.
  • Main validation: https://github.com/OilpriceAPI/google-sheets-addin/actions/runs/31499079799
  • Main docs deployment: https://github.com/OilpriceAPI/google-sheets-addin/actions/runs/31499079777
  • Fresh-clone proof: 98/98 tests, dependency audit 0 at moderate, clasp 3.3.0, four-file deployment package, assets, portfolio packages, public claims, and secret scans green.
  • Current deployable file SHA-256 values:
    • Code.gs: 03582b77bd1604366a6fcd44e1fff23d67c792bc9abcd9f36af299f3b655a09a
    • Sidebar.html: a9bdf7c923a0d38636bec9b04a280b1945500a07fea52f2ff236e7d74efea3ee
    • FetchDialog.html: 78f4f2fad0f846b347dc27ac74160624e327599709b854981b3517c2ae61e542
    • appsscript.json: 45f51456777cc4f9760bc4998c2f24492688817d3182850e54d3d2433844521e

Do not create an immutable version or change Marketplace App Configuration until the API v2/runtime release owner provides an explicit production-green signal. The public product contract must say 50 requests per day; never infer a monthly window from legacy fields.

Immutable v13 release checklist

  • Record the explicit API v2 production-green receipt. Independently verify the canonical limits endpoint reports 50 requests per day and that public product facts no longer expose the stale 50-per-month semantics.
  • Verify origin/main is still the exact reviewed SHA above, main CI is green, open release PRs are zero, and the four deployable hashes still match. If main changes, stop and re-run the full gate; do not cut from an unreviewed SHA.
  • Confirm the protected apps-script-production environment is targeting the unchanged production Script ID and that local/CI clasp credentials are not printed or committed.
  • Dispatch apps-script-release.yml from main with description OilPriceAPI for Google Sheets 1.3.1 cache-isolation recovery.
  • Require the run to report audit 0, 98/98 tests, exactly four pushed files, and Created version 13. If Google returns any other version, record the actual immutable number and stop calling it v13.
  • Clone the created immutable version into a new scratch directory and compare its four files byte-for-byte with the reviewed package/hashes above. Do not rely only on the successful push log.
  • Capture the workflow URL, head SHA, immutable number/description, version-list receipt, and remote-clone comparison here.
  • Preserve Marketplace version 11 and its current App Configuration values as the rollback receipt before any draft edit.
  • Change only the Marketplace draft script-version field from 11 to the proven candidate; preserve Script ID, Public visibility, install settings, scopes, and developer fields. Save Draft only. Do not publish the Store Listing yet.
  • Verify the installed tester actually loads runtime 1.3.1; a Latest Code editor deployment or a #NAME? formula result is not candidate evidence.

Installed-account disposable-sheet smoke

Use the already-installed authorized tester account and a new blank spreadsheet named OPA Marketplace Candidate v13 Smoke 2026-08-11. Do not uninstall the existing add-on, touch existing sheets, use customer data, put an API key in a cell/URL/screenshot, or expose account/contact information.

  • Open the installed OilPriceAPI add-on, choose Use in this document when offered, refresh once, and confirm exactly one add-on context/menu.
  • Open the sidebar and confirm runtime 1.3.1/candidate identity. The new spreadsheet must initially report No key is stored; a key from another spreadsheet must not cross into it.
  • Before saving a key, =OILPRICE_PRICE("WTI_USD") must return actionable #AUTH_REQUIRED without an API request.
  • Save only the approved synthetic non-customer key. Confirm the input clears, the stored value is never displayed, and Test connection reports Connection and response schema verified.
  • Run =OILPRICE_PRICE("WTI_USD"); require a finite numeric value.
  • Run =OILPRICE_UNIT("WTI_USD"), =OILPRICE_STATUS("WTI_USD"), and =OILPRICE_INFO("WTI_USD"); require non-empty unit/source, parseable source timestamp, freshness state, and no fabricated metadata.
  • Run =OILPRICE_HISTORY("WTI_USD",1); require timestamp/value rows with parseable timestamps and finite numeric prices.
  • Run =OILPRICE_CODES() and =OILPRICE_GET("/v1/prices/latest","by_code=WTI_USD"); require readable non-empty tables.
  • Put WTI_USD, BRENT_CRUDE_USD, and one valid third code in a three-cell range and run =OILPRICE_TABLE(range); require one stable spilled batch table and verify execution/request evidence does not show per-cell request fan-out.
  • Run =OILPRICE_GET("/v1/users/me","") and a query containing api_key; both must fail locally before an API request.
  • Save a deliberately invalid synthetic key, run Test connection, and require actionable invalid/revoked-key recovery. Restore the valid fixture, run Test connection, and require the same price formula to recover immediately; this proves generation invalidation after key replacement.
  • Run an invalid commodity code and require readable #INVALID_CODE/#NO_DATA, not a blank success or raw exception.
  • If approved non-customer entitlement and exhausted-quota fixtures already exist, verify 403 upgrade and 429 retry-later recovery plus Test Connection cache clearing. Do not create a customer identity, change billing, or burn the 50/day allowance merely to manufacture these states; the exact 98-test suite remains the required deterministic proof otherwise.
  • Confirm the sidebar does not display a monthly request counter or reinterpret a legacy requests_this_month value.
  • Refresh Last request diagnostic and verify it contains bounded code/status/duration/path/timestamp only: no API key and no query string.
  • Delete the key. Confirm the sidebar returns to No key is stored, diagnostics clear, and the formula returns #AUTH_REQUIRED again.
  • Review Apps Script Executions and API attribution for the smoke window: no raw key, query values, unexpected exception loop, repeated retry storm, unexplained 4xx/5xx, or excessive request count.
  • Capture redacted browser screenshots of sidebar connection, numeric/info/history/batch results, invalid-key recovery, and final no-key state. Record spreadsheet ID/URL only in an access-controlled receipt if it reveals the tester identity.
  • Trash the disposable sheet after evidence is preserved.

This installed-account smoke is necessary candidate evidence, but it does not replace a clean-account install.

Publication and clean-account gate

  • Only after every candidate check passes, publish/select the tested immutable version in Marketplace. Record the exact console state and timestamp; do not claim the new runtime is public from a repo merge or Apps Script version alone.
  • Repeat the formula/recovery smoke through the public listing and review production executions/logs.
  • Use a pre-authorized dedicated clean test identity for a new Marketplace install and consent flow. No such separate identity is currently available in the repository, environment, or authorized browser session; do not create/enroll a customer or personal identity to fill this gap.
  • Attach the clean-account install, consent, Use in this document, connection, formula, recovery, and key-deletion receipts.
  • Update repository/operator/website version claims only from verified console and public-runtime state.

Next owner action

@karlwaldman: after the explicit API v2 green signal, execute the immutable workflow and installed-account candidate smoke above. Separately provision or authorize a dedicated non-customer Google test identity for the clean-install gate without using customer data.

Closure rule

Keep this issue open until the tested runtime is selected in public Marketplace, the published-artifact smoke is green, and a separate clean-account install/formula receipt is attached. Do not hide the missing identity or infer Google state without console/public evidence.

Metadata

Metadata

Assignees

Labels

change-risk:lowIsolated, reversible change with limited blast radiuscommitment:discoveryNeeds evidence, a decision, or a bounded experiment before deliveryeconomics:missingNo credible near-term economic case is recordedeffort:unknownTotal delivery effort has not been estimatedinaction-risk:lowNo material near-term downside from deferringreality:needs-verificationMore work is required to establish current implementation scope

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions