From 6bd9c89c220bdb6c36477d1a6e9f17f0b39b77bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=B6kdemir?= Date: Wed, 14 Oct 2026 13:18:28 +0300 Subject: [PATCH] Prepare v0.3.0 release --- CHANGELOG.md | 2 ++ dist/index.cjs | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/version.js | 2 +- test/hardening.test.js | 5 +++-- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d1c144..68a6fc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +## 0.3.0 + - Classify Admin, Storefront, Customer Account, and ambiguous GraphQL operations independently using nearby source context. - Add explicit Shopify API version status and evidence applicability to CLI, Action, JSON, human, and SARIF reports. - Make standalone GraphQL documents without API client context UNKNOWN and restrict explicit configuration scans to the selected app root. diff --git a/dist/index.cjs b/dist/index.cjs index 8cca2f5..3698451 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -22257,7 +22257,7 @@ var import_node_path3 = __toESM(require("node:path"), 1); var import_node_crypto = require("node:crypto"); // src/version.js -var TOOL_VERSION = "0.2.4"; +var TOOL_VERSION = "0.3.0"; // src/analyzer/index.js var import_node_fs2 = __toESM(require("node:fs"), 1); diff --git a/package-lock.json b/package-lock.json index 3891144..7e76be6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "shopify-scope-guard", - "version": "0.2.4", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "shopify-scope-guard", - "version": "0.2.4", + "version": "0.3.0", "license": "MIT", "dependencies": { "@iarna/toml": "^2.2.5", diff --git a/package.json b/package.json index 634df44..8c8cada 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shopify-scope-guard", - "version": "0.2.4", + "version": "0.3.0", "description": "Review Shopify app OAuth and API access scopes against static repository evidence with a CLI and GitHub Action.", "type": "module", "bin": { diff --git a/src/version.js b/src/version.js index e6993a2..4687ae8 100644 --- a/src/version.js +++ b/src/version.js @@ -1,2 +1,2 @@ // Generated from package.json. -export const TOOL_VERSION = "0.2.4"; +export const TOOL_VERSION = "0.3.0"; diff --git a/test/hardening.test.js b/test/hardening.test.js index ac8ba9b..077a74a 100644 --- a/test/hardening.test.js +++ b/test/hardening.test.js @@ -7,6 +7,7 @@ import { spawnSync } from 'node:child_process'; import { audit } from '../src/analyzer/index.js'; import { parseGraphQL } from '../src/graphql/index.js'; const cli=path.resolve('src/cli/index.js'),action=path.resolve('dist/index.cjs'); +const packageVersion=JSON.parse(fs.readFileSync('package.json','utf8')).version; function fixture(t,scopes=''){const root=fs.mkdtempSync(path.join(os.tmpdir(),'scope-hardening-'));t.after(()=>fs.rmSync(root,{recursive:true,force:true}));fs.writeFileSync(path.join(root,'shopify.app.toml'),`[access_scopes]\nscopes="${scopes}"\n`);return root;} const adminDocument = query => `const response = await admin.graphql(\`#graphql\n${query}\n\`);`; test('local fragments, aliases and inline fragments preserve field paths',()=>{ @@ -71,7 +72,7 @@ test('selecting one nested app restricts code scanning to its configuration root assert.equal(report.findings.length,0); }); test('relative configuration is resolved inside root and ambiguity is rejected',t=>{ - const root=fixture(t);fs.renameSync(path.join(root,'shopify.app.toml'),path.join(root,'shopify.app.dev.toml'));fs.writeFileSync(path.join(root,'shopify.app.prod.toml'),'[access_scopes]\nscopes=""');assert.throws(()=>audit({root}),/Multiple/);assert.equal(audit({root,configPath:'shopify.app.dev.toml'}).tool.version,'0.2.4');assert.throws(()=>audit({root,configPath:'../external.toml'}),/inside/); + const root=fixture(t);fs.renameSync(path.join(root,'shopify.app.toml'),path.join(root,'shopify.app.dev.toml'));fs.writeFileSync(path.join(root,'shopify.app.prod.toml'),'[access_scopes]\nscopes=""');assert.throws(()=>audit({root}),/Multiple/);assert.equal(audit({root,configPath:'shopify.app.dev.toml'}).tool.version,packageVersion);assert.throws(()=>audit({root,configPath:'../external.toml'}),/inside/); }); test('symlinks and oversized files are skipped; malformed config is redacted',t=>{ const root=fixture(t),outside=fixture(t);fs.writeFileSync(path.join(outside,'query.graphql'),'mutation { productCreate(product:{title:"x"}){product{id}}}'); @@ -86,7 +87,7 @@ test('CLI policies reject typo and missing values',t=>{ test('Action outcome agrees with none and medium policies and returns JSON file',t=>{ const root=fixture(t,'read_products,write_products'),out=path.join(root,'outputs');fs.writeFileSync(out,''); const run=threshold=>spawnSync(process.execPath,[action],{encoding:'utf8',env:{...process.env,INPUT_PATH:root,INPUT_FAIL_ON:threshold,GITHUB_OUTPUT:out,RUNNER_TEMP:root}}); - assert.equal(run('none').status,0);assert.equal(run('medium').status,1);const text=fs.readFileSync(out,'utf8');assert.match(text,/outcome<<[^\n]+\npassed/);assert.match(text,/outcome<<[^\n]+\nfailed/);const report=text.match(/report<<([^\n]+)\n([^\n]+)\n\1/);assert.ok(report);assert.equal(JSON.parse(fs.readFileSync(report[2],'utf8')).tool.version,'0.2.4');assert.equal(run('typo').status,2); + assert.equal(run('none').status,0);assert.equal(run('medium').status,1);const text=fs.readFileSync(out,'utf8');assert.match(text,/outcome<<[^\n]+\npassed/);assert.match(text,/outcome<<[^\n]+\nfailed/);const report=text.match(/report<<([^\n]+)\n([^\n]+)\n\1/);assert.ok(report);assert.equal(JSON.parse(fs.readFileSync(report[2],'utf8')).tool.version,packageVersion);assert.equal(run('typo').status,2); }); test('read analytics scopes cannot authorize write mutations',t=>{