Skip to content

Commit a82f1b9

Browse files
license file added and updated readme md
1 parent 59b4983 commit a82f1b9

22 files changed

Lines changed: 3597 additions & 56 deletions

‎.gitattributes‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Generated compliance artifacts are written with LF by Node. Without this, a
2+
# contributor with core.autocrlf=true checks them out as CRLF, and
3+
# `pnpm licences:check` reports them stale with no useful diagnostic — the
4+
# content is identical and only the line endings differ.
5+
* text=auto eol=lf
6+
7+
*.md text eol=lf
8+
*.txt text eol=lf
9+
*.mjs text eol=lf
10+
*.json text eol=lf
11+
*.yml text eol=lf
12+
13+
# Binary — never normalise.
14+
*.png binary
15+
*.woff binary
16+
*.woff2 binary

‎.github/workflows/compliance.yml‎

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
name: Licence compliance
2+
3+
# Makes the licence position self-enforcing. Every check here exists because
4+
# something was found missing in the review; the point is that it cannot
5+
# regress quietly.
6+
#
7+
# The central concern for this repo is different from aistudio-server. This is
8+
# a publicly deployed browser app, so serving the bundle IS distribution and
9+
# the attribution conditions of ~54 permissive licences apply on every page
10+
# load. esbuild strips comments during minification, so attribution has to be
11+
# emitted deliberately — and CI has to confirm it still is.
12+
13+
on:
14+
push:
15+
branches: [main, master]
16+
pull_request:
17+
schedule:
18+
# Weekly. Upstream packages change licences occasionally and silently.
19+
- cron: "0 6 * * 1"
20+
workflow_dispatch:
21+
22+
permissions:
23+
contents: read
24+
25+
defaults:
26+
run:
27+
working-directory: Benchmarking
28+
29+
jobs:
30+
compliance:
31+
name: Licence files, attribution, inventory
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v4
35+
36+
- uses: pnpm/action-setup@v4
37+
with:
38+
# The app lives in Benchmarking/, and there is no root package.json.
39+
# `defaults.run.working-directory` only affects `run:` steps — `uses:`
40+
# steps run from the workspace root, so without this the action looks
41+
# for <workspace>/package.json, finds nothing, and fails before
42+
# setup-node runs.
43+
#
44+
# The version itself comes from the `packageManager` field in that
45+
# file. Pinning it matters: this workflow's inventory check compares
46+
# committed artifacts against `pnpm licenses list --prod --json`
47+
# output, whose shape has changed across pnpm majors. An unpinned
48+
# bump would turn the artifacts "stale" and report it as a missing
49+
# `pnpm licences` run.
50+
package_json_file: Benchmarking/package.json
51+
52+
- uses: actions/setup-node@v4
53+
with:
54+
node-version: 22
55+
cache: pnpm
56+
cache-dependency-path: Benchmarking/pnpm-lock.yaml
57+
58+
- name: Install (frozen lockfile)
59+
# --frozen-lockfile is what makes the ^ ranges in package.json safe.
60+
# An unfrozen install would silently resolve a different tree, and the
61+
# committed inventory would stop describing what actually ships.
62+
run: pnpm install --frozen-lockfile
63+
64+
- name: Run compliance checks
65+
# Same script as `pnpm compliance` locally, so the feedback loop does
66+
# not require a push. Covers: LICENSE completeness and filled-in
67+
# copyright, required files present, package.json license field,
68+
# no CDN origins, the footer attribution link, and inventory freshness.
69+
run: pnpm compliance
70+
71+
bundle-attribution:
72+
name: Built bundle carries attribution
73+
runs-on: ubuntu-latest
74+
steps:
75+
- uses: actions/checkout@v4
76+
- uses: pnpm/action-setup@v4
77+
with:
78+
# The app lives in Benchmarking/, and there is no root package.json.
79+
# `defaults.run.working-directory` only affects `run:` steps — `uses:`
80+
# steps run from the workspace root, so without this the action looks
81+
# for <workspace>/package.json, finds nothing, and fails before
82+
# setup-node runs.
83+
#
84+
# The version itself comes from the `packageManager` field in that
85+
# file. Pinning it matters: this workflow's inventory check compares
86+
# committed artifacts against `pnpm licenses list --prod --json`
87+
# output, whose shape has changed across pnpm majors. An unpinned
88+
# bump would turn the artifacts "stale" and report it as a missing
89+
# `pnpm licences` run.
90+
package_json_file: Benchmarking/package.json
91+
- uses: actions/setup-node@v4
92+
with:
93+
node-version: 22
94+
cache: pnpm
95+
cache-dependency-path: Benchmarking/pnpm-lock.yaml
96+
97+
- run: pnpm install --frozen-lockfile
98+
99+
- name: Build
100+
env:
101+
# vite.config.ts throws without this. Value is irrelevant to the
102+
# licence check — nothing is called at build time.
103+
VITE_API_URL: https://example.invalid
104+
run: pnpm build
105+
106+
- name: Licence text is present in the deployed output
107+
# This is the check that actually matters. Everything else verifies
108+
# files exist in the repo; this verifies the notices reach the person
109+
# receiving the bundle. Before this was fixed, `grep -c Copyright`
110+
# across dist/assets/*.js returned 0.
111+
run: |
112+
file=dist/third-party-licences.txt
113+
if [ ! -f "$file" ]; then
114+
echo "::error::$file was not emitted into the build output."
115+
echo "Vite copies public/ into dist/. Run 'pnpm licences' and commit."
116+
exit 1
117+
fi
118+
119+
copyrights=$(grep -c "Copyright" "$file" || true)
120+
if [ "$copyrights" -lt 40 ]; then
121+
echo "::error::only $copyrights copyright notices in $file — expected 40+."
122+
exit 1
123+
fi
124+
echo "$copyrights copyright notices present."
125+
126+
# Apache-2.0 section 4(d): echarts ships a NOTICE whose attributions
127+
# must be reproduced in any distribution of a derivative work.
128+
grep -q "The Apache Software Foundation" "$file" || {
129+
echo "::error::the Apache ECharts NOTICE attribution is missing (Apache-2.0 s4(d))."
130+
exit 1
131+
}
132+
echo "Apache NOTICE attribution present."
133+
134+
# OFL-1.1 section 2: the licence must accompany the bundled fonts.
135+
grep -qi "SIL OPEN FONT LICENSE" "$file" || {
136+
echo "::error::the OFL-1.1 text is missing, but Inter is bundled (OFL s2)."
137+
exit 1
138+
}
139+
echo "OFL-1.1 text present."
140+
141+
- name: The app links to it, with the production base path
142+
run: |
143+
# A licence file nobody can reach is not attribution. The footer link
144+
# is the delivery mechanism, and the base path has to survive the
145+
# build — the app is served under /aistudio/, not /.
146+
if ! grep -rq "/aistudio/third-party-licences.txt" dist/assets/*.js; then
147+
echo "::error::the bundle does not reference /aistudio/third-party-licences.txt."
148+
echo "Check LICENCES_URL in src/app/constants.ts and the footer link."
149+
exit 1
150+
fi
151+
echo "Bundle links the licence file at the correct base path."
152+
153+
- uses: actions/upload-artifact@v4
154+
if: always()
155+
with:
156+
name: third-party-licences
157+
path: Benchmarking/dist/third-party-licences.txt
158+
if-no-files-found: warn

‎.gitignore‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Repository-root ignores.
2+
#
3+
# Benchmarking/ has its own .gitignore for build output and node_modules; this
4+
# one covers things that appear at the root, where there was previously no
5+
# .gitignore at all.
6+
7+
# IDE
8+
.idea/
9+
.vscode/*
10+
!.vscode/extensions.json
11+
*.iml
12+
13+
# OS
14+
.DS_Store
15+
Thumbs.db
16+
17+
# Env — never commit. Benchmarking/.env.example is the template.
18+
.env
19+
.env.*
20+
!.env.example
21+
22+
# Deploy
23+
.vercel

‎Benchmarking/.env.example‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1-
VITE_API_URL = "https://corespan.ddnsgeek.com:8443"
2-
BROWSER=chrome
1+
# Backend API origin. Required — the dev server throws on startup if unset.
2+
# Point this at wherever your aistudio-server instance is reachable.
3+
VITE_API_URL="http://localhost:8002"
4+
5+
# Optional: browser to open when the dev server starts (chrome, firefox,
6+
# safari, or a path to a binary). Leave unset to use the system default.
7+
BROWSER=chrome

‎Benchmarking/CLAUDE.md‎

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ client, UI primitives, chart wrappers — lives locally under `src/shared/`.
2323

2424
---
2525

26-
## Shared Packages
26+
## Shared Code
2727

28-
This app consumes the workspace packages via `workspace:*` and path aliases
29-
(wired in `vite.config.ts` + `tsconfig*.json`):
28+
There are no workspace packages and no private registry — every dependency in
29+
`package.json` is public on npm, so a clean `pnpm install` is all a fresh
30+
checkout needs.
3031

31-
- `@corespan/ui` — shared components (peer deps only — this app provides Mantine/React/etc.)
32-
- `@corespan/api` — zero-dep HTTP client (`createApiClient`)
33-
- `@corespan/utils` — zero-dep helpers
32+
Shared code lives under `src/shared/` and is imported through the single `@`
33+
alias (`@` → `src`, wired in `vite.config.ts` + `tsconfig*.json`):
3434

35-
Never import across workspace boundaries with relative paths — always use the `@corespan/` alias.
35+
- `@/shared/api` — HTTP client (`baseClient`), `API_ORIGIN`, TanStack `queryClient`
36+
- `@/shared/ui` — local primitives: `CoreChart`, `CoreTable`, `CoreForm`, `CoreIcon`
37+
38+
Prefer the `@` alias over deep relative paths (`../../../shared/...`).
3639

3740
---
3841

@@ -41,14 +44,24 @@ Never import across workspace boundaries with relative paths — always use the
4144
```
4245
src/
4346
├── app/
44-
│ └── App.tsx # Mantine + QueryClient providers
47+
│ ├── App.tsx # Mantine + QueryClient providers
48+
│ ├── constants.ts
49+
│ └── layout/ # AppLayout, AppFooter, PageShell
4550
├── features/
46-
│ └── benchmarks/
47-
│ └── Benchmarks.tsx # Starter page
51+
│ ├── about/ # AboutUs page + components
52+
│ └── benchmarks/ # The main feature
53+
│ ├── Benchmarks.tsx
54+
│ ├── components/ # Tables, charts, modals, log streams
55+
│ ├── data/ # Query keys, services
56+
│ ├── lib/ # Pure helpers (maskIp, toBenchmarkRows, ...)
57+
│ └── store/ # Zustand stores (useJupyterRunStore, ...)
4858
├── shared/
49-
│ └── api/
50-
│ ├── baseClient.ts # Single createApiClient instance — never create a second
51-
│ └── queryClient.ts # TanStack QueryClient config
59+
│ ├── api/
60+
│ │ ├── baseClient.ts # Single createApiClient instance — never create a second
61+
│ │ ├── config.ts # API_ORIGIN, resolved from VITE_API_URL
62+
│ │ ├── core/ # Client, middleware, error types
63+
│ │ └── queryClient.ts # TanStack QueryClient config
64+
│ └── ui/ # CoreChart, CoreTable, CoreForm, CoreIcon
5265
├── index.css
5366
└── main.tsx # React 19 StrictMode entry point
5467
```
@@ -64,6 +77,11 @@ import it — never instantiate a second client.
6477

6578
## Development Proxy
6679

67-
The Vite config has no backend proxy yet. When the app needs to call the backend,
68-
add a proxy block mirroring `apps/composer/vite.config.ts` and document the required
69-
`.env` vars here (see `.env.example`).
80+
`vite.config.ts` proxies two paths to `VITE_API_URL`:
81+
82+
- `/api` — the versioned API namespace
83+
- `/health` — the backend's health probe, which sits at the root rather than
84+
under `/api/v1` and so needs its own entry
85+
86+
`VITE_API_URL` is **required** — the dev server throws on startup without it.
87+
Copy `.env.example` to `.env` and point it at your backend.

0 commit comments

Comments
 (0)