Skip to content

Commit 28edadd

Browse files
committed
Modernize for PastureStack compatibility
1 parent 80270e0 commit 28edadd

51 files changed

Lines changed: 9552 additions & 670 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitattributes‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* text=auto eol=lf

‎.github/workflows/build-release.yaml‎

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: CodeQL verification
2+
3+
on:
4+
push:
5+
branches:
6+
- 'verification/api-explorer-*'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: api-explorer-codeql-${{ github.ref }}
14+
cancel-in-progress: false
15+
16+
jobs:
17+
analyze:
18+
runs-on: ubuntu-24.04
19+
timeout-minutes: 45
20+
steps:
21+
- name: Check out candidate
22+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2
23+
with:
24+
fetch-depth: 0
25+
persist-credentials: false
26+
27+
- name: Verify candidate shape
28+
shell: bash
29+
run: |
30+
set -euo pipefail
31+
test -z "$(git status --porcelain)"
32+
test "$(git rev-list --count 80270e0af984025b14afc61c0d0b0a4f08d968bf..HEAD)" -eq 1
33+
34+
- name: Initialize CodeQL
35+
uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
36+
with:
37+
languages: javascript-typescript
38+
build-mode: none
39+
config: |
40+
queries:
41+
- uses: security-extended
42+
threat-models: local
43+
44+
- name: Analyze without publishing temporary alerts
45+
uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7
46+
with:
47+
category: /language:javascript-typescript
48+
upload: never
49+
output: codeql-results
50+
51+
- name: Reject Critical and High findings
52+
shell: bash
53+
run: |
54+
set -euo pipefail
55+
python3 - <<'PY'
56+
import glob
57+
import json
58+
59+
blocked = []
60+
unresolved = []
61+
total = 0
62+
for path in glob.glob('codeql-results/**/*.sarif', recursive=True):
63+
with open(path, encoding='utf-8') as stream:
64+
sarif = json.load(stream)
65+
for run in sarif.get('runs', []):
66+
rules = {rule.get('id'): rule for rule in run.get('tool', {}).get('driver', {}).get('rules', [])}
67+
for extension in run.get('tool', {}).get('extensions', []):
68+
rules.update({rule.get('id'): rule for rule in extension.get('rules', [])})
69+
for result in run.get('results', []):
70+
total += 1
71+
rule_id = result.get('ruleId')
72+
rule = rules.get(rule_id)
73+
if rule is None:
74+
unresolved.append((rule_id, 'missing rule metadata'))
75+
continue
76+
try:
77+
score = float(rule.get('properties', {}).get('security-severity', '0'))
78+
except (TypeError, ValueError):
79+
unresolved.append((rule_id, 'invalid security severity'))
80+
continue
81+
if score >= 7.0:
82+
location = result.get('locations', [{}])[0].get('physicalLocation', {})
83+
blocked.append((rule_id, score, location.get('artifactLocation', {}).get('uri', 'unknown'), location.get('region', {}).get('startLine', 0)))
84+
print(f'codeql_total={total}')
85+
print(f'codeql_critical_high={len(blocked)}')
86+
print(f'codeql_unresolved_rule_metadata={len(unresolved)}')
87+
for finding in blocked:
88+
print(f'{finding[0]}\t{finding[1]}\t{finding[2]}:{finding[3]}')
89+
for finding in unresolved:
90+
print(f'{finding[0]}\t{finding[1]}')
91+
if blocked or unresolved:
92+
raise SystemExit(1)
93+
PY
94+
95+
- name: Upload verification evidence
96+
if: always()
97+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
98+
with:
99+
name: api-explorer-codeql-${{ github.sha }}
100+
path: codeql-results/
101+
if-no-files-found: error
102+
retention-days: 7
103+
compression-level: 9

‎.github/workflows/fossa.yml‎

Lines changed: 0 additions & 34 deletions
This file was deleted.

‎.github/workflows/pr-build-check.yaml‎

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
name: Security release gate
2+
3+
on:
4+
push:
5+
branches:
6+
- 'verification/api-explorer-*'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
12+
concurrency:
13+
group: api-explorer-security-${{ github.ref }}
14+
cancel-in-progress: false
15+
16+
jobs:
17+
build-test-scan:
18+
runs-on: ubuntu-24.04
19+
timeout-minutes: 45
20+
env:
21+
TRIVY_IMAGE: aquasec/trivy:0.73.0@sha256:7cced7cae583819fc7806d4cbc0dbbc7cad18b99f7d3e235192e6da8c091045c
22+
steps:
23+
- name: Check out candidate
24+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.0.2
25+
with:
26+
fetch-depth: 0
27+
persist-credentials: false
28+
29+
- name: Install Node.js
30+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
31+
with:
32+
node-version: '24.15.0'
33+
cache: npm
34+
35+
- name: Verify source identity and lock files
36+
shell: bash
37+
run: |
38+
set -euo pipefail
39+
test -z "$(git status --porcelain)"
40+
test "$(git rev-list --count 80270e0af984025b14afc61c0d0b0a4f08d968bf..HEAD)" -eq 1
41+
mkdir -p evidence
42+
git rev-parse HEAD > evidence/source-revision.txt
43+
sha256sum package.json package-lock.json .github/workflows/*.yml > evidence/source-locks.sha256
44+
node --version | tee evidence/node-version.txt
45+
npm --version | tee evidence/npm-version.txt
46+
47+
- name: Install, test, audit, and build twice
48+
shell: bash
49+
run: |
50+
set -euo pipefail
51+
npm ci --ignore-scripts --omit=optional --no-audit --no-fund
52+
npm run test:security
53+
npm audit --omit=dev --json > evidence/npm-audit-runtime.json
54+
npm audit --json > evidence/npm-audit-all.json
55+
npm run ci
56+
version=$(node -p "require('./package.json').version")
57+
artifact="dist/${version}.tar.gz"
58+
cp "$artifact" /tmp/api-explorer-first.tar.gz
59+
rm -rf dist tmp
60+
npm run build
61+
cmp /tmp/api-explorer-first.tar.gz "$artifact"
62+
sha256sum "$artifact" > evidence/product-artifact.sha256
63+
tar -tzf "$artifact" > evidence/product-members.txt
64+
65+
- name: Generate package SBOM
66+
shell: bash
67+
run: |
68+
set -euo pipefail
69+
npm exec --yes --package='@cyclonedx/cyclonedx-npm@6.0.1' -- cyclonedx-npm \
70+
--output-format JSON \
71+
--spec-version 1.6 \
72+
--output-file evidence/api-explorer.cdx.json
73+
74+
- name: Scan immutable source and product
75+
shell: bash
76+
run: |
77+
set -euo pipefail
78+
docker pull "$TRIVY_IMAGE"
79+
cache="$RUNNER_TEMP/trivy-cache"
80+
source_tree="$(mktemp -d)"
81+
product_tree="$(mktemp -d)"
82+
trap 'rm -rf "$source_tree" "$product_tree"' EXIT
83+
mkdir -p "$cache" "$product_tree"
84+
git archive --format=tar HEAD | tar -xf - -C "$source_tree"
85+
version=$(node -p "require('./package.json').version")
86+
tar -xzf "dist/${version}.tar.gz" -C "$product_tree"
87+
docker run --rm -v "$cache:/root/.cache/trivy" "$TRIVY_IMAGE" image --download-db-only
88+
docker run --rm -v "$source_tree:/scan:ro" -v "$PWD/evidence:/evidence" -v "$cache:/root/.cache/trivy" "$TRIVY_IMAGE" fs \
89+
--skip-db-update --offline-scan --scanners vuln,secret --format json --output /evidence/source-security.json /scan
90+
docker run --rm -v "$product_tree:/scan:ro" -v "$PWD/evidence:/evidence" -v "$cache:/root/.cache/trivy" "$TRIVY_IMAGE" rootfs \
91+
--skip-db-update --offline-scan --scanners vuln,secret --format json --output /evidence/product-security.json /scan
92+
93+
- name: Enforce candidate security
94+
shell: bash
95+
run: |
96+
set -euo pipefail
97+
: > evidence/security-summary.txt
98+
for scope in source product; do
99+
report="evidence/${scope}-security.json"
100+
secrets=$(jq '[.Results[]?.Secrets[]?] | length' "$report")
101+
critical=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "CRITICAL")] | length' "$report")
102+
high=$(jq '[.Results[]?.Vulnerabilities[]? | select(.Severity == "HIGH")] | length' "$report")
103+
printf '%s_secrets=%s\n%s_critical=%s\n%s_high=%s\n' "$scope" "$secrets" "$scope" "$critical" "$scope" "$high" | tee -a evidence/security-summary.txt
104+
test "$secrets" -eq 0
105+
test "$critical" -eq 0
106+
test "$high" -eq 0
107+
done
108+
jq -e '.metadata.vulnerabilities.critical == 0 and .metadata.vulnerabilities.high == 0' evidence/npm-audit-runtime.json >/dev/null
109+
jq -e '.metadata.vulnerabilities.critical == 0 and .metadata.vulnerabilities.high == 0' evidence/npm-audit-all.json >/dev/null
110+
jq -e '.bomFormat == "CycloneDX" and .specVersion == "1.6" and (.components | length) > 0' evidence/api-explorer.cdx.json >/dev/null
111+
112+
- name: Upload reviewed evidence
113+
if: always()
114+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
115+
with:
116+
name: api-explorer-security-${{ github.sha }}
117+
path: evidence/
118+
if-no-files-found: error
119+
retention-days: 30
120+
compression-level: 9
121+
122+
- name: Clean runner resources
123+
if: always()
124+
shell: bash
125+
run: |
126+
set +e
127+
docker image rm -f "$TRIVY_IMAGE" 2>/dev/null
128+
docker builder prune --all --force >/dev/null 2>&1
129+
rm -rf node_modules dist tmp

‎COMPATIBILITY.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Compatibility Contract
2+
3+
API Explorer preserves schema discovery, resource links, collection and action forms, pagination, filtering, authentication handling, HTML embedding, and template data expected by compatible APIs.
4+
5+
Visible product naming and package ownership use PastureStack. Historical API resource names, schema fields, enum values, response links, and compatibility CSS hooks remain unchanged where supplied by or coupled to the remote API.
6+
7+
The Server packaging contract currently consumes the `1.1.15` static archive and exposes its `ui.min.js` and `ui.min.css` files below `/api-ui/`. The `1.1.16` security candidate preserves that archive layout; changing the Server default still requires a coordinated embedded-server test.
8+
9+
The release keeps the reviewed Bootstrap 3.4.1 CSS and font layout contract as
10+
static, attributed assets. It does not load Bootstrap JavaScript. A small
11+
PastureStack-owned compatibility layer implements only the modal and filter
12+
dropdown behavior used by this explorer. Native `title` text provides field
13+
help; executable tooltip, popover, button, and generic Bootstrap data APIs are
14+
not part of the artifact.
15+
16+
Before release, validate read-only and mutating resources, actions, pagination, filters, authentication failures, HTML embedding, escaping, cross-origin behavior, and `en-US`/`zh-TW` selection against an isolated compatible server.

‎ORIGIN.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Origin and Attribution
2+
3+
This repository is a GitHub fork of `https://github.com/rancher/api-ui`.
4+
5+
- Preserved upstream boundary: `80270e0af984025b14afc61c0d0b0a4f08d968bf`
6+
- Boundary author: Neil MacDougall
7+
- Boundary date: 2026-06-03
8+
- Migration model: unchanged upstream history followed by one PastureStack maintenance commit
9+
10+
Original commit identifiers, authors, dates, tags, copyright notices, the root Apache-2.0 license, and bundled dependency legal files remain authoritative for inherited work. PastureStack claims only its subsequent modifications and does not imply affiliation with the original maintainers.

0 commit comments

Comments
 (0)