diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..1b72954ee --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,85 @@ +name: Bug report +description: Report a reproducible defect in the proxy, CLI, dashboard, docs, or packaging. +title: "[Bug]: " +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for the report. Please include a minimal reproduction and the exact environment details. + + - type: textarea + id: summary + attributes: + label: Summary + description: What happened, and what did you expect instead? + placeholder: A clear and concise description of the bug. + validations: + required: true + + - type: textarea + id: reproduction + attributes: + label: Reproduction + description: List the exact steps, commands, and config shape needed to reproduce the problem. + placeholder: | + 1. Run `ocx init` + 2. Start the proxy with ... + 3. Open ... + 4. Observe ... + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Logs and screenshots + description: Paste relevant logs, stack traces, request IDs, or screenshots. + render: shell + + - type: dropdown + id: area + attributes: + label: Area + options: + - CLI + - Proxy runtime + - GUI dashboard + - Docs + - Packaging or install + - Provider adapter + - Other + validations: + required: true + + - type: input + id: version + attributes: + label: Version + description: The installed `@bitkyc08/opencodex` version or commit SHA. + placeholder: 2.7.7 + + - type: input + id: os + attributes: + label: OS + description: Operating system and version. + placeholder: Windows 11, macOS 15, Ubuntu 24.04 + + - type: textarea + id: config + attributes: + label: Config shape + description: Share a redacted config snippet if the bug depends on provider or routing setup. + render: json + + - type: checkboxes + id: checks + attributes: + label: Checks + options: + - label: I searched existing issues and docs first. + required: true + - label: I removed secrets, tokens, and personal data from logs and screenshots. + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..bf280d67c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Security policy + url: https://github.com/lidge-jun/opencodex/blob/main/SECURITY.md + about: Read the supported-version and reporting guidance before sharing security-sensitive details. + - name: Contributing guide + url: https://lidge-jun.github.io/opencodex/contributing/ + about: Review setup, build, and verification guidance for contributors. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..6a87d7dd9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,34 @@ +name: Feature request +description: Propose a new capability or workflow improvement. +title: "[Feature]: " +labels: + - enhancement +body: + - type: textarea + id: problem + attributes: + label: Problem to solve + description: What workflow or limitation are you trying to improve? + placeholder: I want opencodex to ... + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: Describe the behavior you want, including any CLI, GUI, or config surface. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: What workarounds or competing approaches did you try? + + - type: textarea + id: context + attributes: + label: Additional context + description: Link docs, screenshots, example configs, or upstream APIs if helpful. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..e740a4d99 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +## Summary + +- Explain the user-visible or maintainer-facing change. + +## Verification + +- List the commands or checks you ran. + +## Checklist + +- [ ] Scope stays focused and avoids unrelated cleanup. +- [ ] Docs or release notes were updated when needed. +- [ ] Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..055692da6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,33 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "dependencies" + + - package-ecosystem: "npm" + directory: "/gui" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "dependencies" + + - package-ecosystem: "npm" + directory: "/docs-site" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "dependencies" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + labels: + - "dependencies" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d7ca2f06..d025a4f28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: run: bun x tsc --noEmit - name: Test - run: bun test tests + run: bun test --isolate tests - name: Privacy scan run: bun run privacy:scan @@ -73,8 +73,16 @@ jobs: - name: Check release helper syntax run: bun build scripts/release.ts --target=bun --outdir=.tmp/ci-release-script-check + - name: GUI lint + run: | + cd gui + bun install --frozen-lockfile + bun run lint + - name: GUI build - run: cd gui && bun install --frozen-lockfile && bun run build + run: | + cd gui + bun run build - name: CLI help smoke run: bun run src/cli/index.ts help diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..8498aa0ae --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +Thanks for helping with opencodex. + +- Start with the canonical guide: [Contributing](https://lidge-jun.github.io/opencodex/contributing/) +- Public user docs live in [`docs-site/`](./docs-site) +- Current maintainer invariants live in [`structure/`](./structure) +- Historical investigations live in [`docs/`](./docs) + +For local development commands, architecture notes, and release workflow details, use the hosted +contributing guide above instead of duplicating instructions here. diff --git a/README.md b/README.md index 58e2c8717..37fe55951 100644 --- a/README.md +++ b/README.md @@ -381,6 +381,8 @@ See the **[Configuration reference](https://lidge-jun.github.io/opencodex/refere The public docs — install, providers, routing, sidecars, Codex integration, Codex App model picker, and CLI/config reference — are built from [`docs-site/`](./docs-site) and published to **[lidge-jun.github.io/opencodex](https://lidge-jun.github.io/opencodex/)**. Maintainer source-of-truth notes live under [`structure/`](./structure). Historical investigations remain under [`docs/`](./docs). +Contributor setup lives in [`CONTRIBUTING.md`](./CONTRIBUTING.md), and security reporting guidance +lives in [`SECURITY.md`](./SECURITY.md). ## Development @@ -402,7 +404,7 @@ the proxy API exposes `/healthz`, `/v1/responses`, `POST /v1/images/generations` bun run dev:gui ``` -See **[Contributing](https://lidge-jun.github.io/opencodex/contributing/)**. +See **[Contributing](./CONTRIBUTING.md)**. ## Disclaimer diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..a9802c920 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ +# Security Policy + +## Supported Versions + +opencodex accepts security fixes on a best-effort basis for these lines: + +| Version | Supported | +| --- | --- | +| `main` | ✅ | +| Latest published npm release | ✅ | +| Older releases | ❌ | + +If you report an issue against an older release, maintainers may ask you to reproduce it on `main` +or the latest published package before triage continues. + +## Reporting a Vulnerability + +Please avoid posting undisclosed vulnerabilities as public GitHub issues. + +- Prefer this repository's GitHub private vulnerability reporting or GitHub Security Advisory flow + when that option is available in the repository UI. +- If no private reporting option is available, do not include exploit details, secrets, or live + targets in a public issue. Open a minimal issue that asks maintainers for a safe coordination path. +- Include affected versions, reproduction steps, impact, and any required configuration details. + +The project does not publish a dedicated private security email in this repository. + +## Response Expectations + +Maintainers will review reports on a best-effort basis. Triage usually starts with: + +- confirming the affected version or commit, +- reproducing the issue locally, +- evaluating impact and safe remediation scope, +- coordinating disclosure timing if a fix is needed. + +## Operational Notes + +- Remove secrets, tokens, cookies, and personal data from screenshots and logs before sharing them. +- For non-sensitive hardening ideas, public issues and pull requests are welcome after disclosure is + no longer sensitive. diff --git a/gui/src/App.tsx b/gui/src/App.tsx index ce9ae49be..dee7f6875 100644 --- a/gui/src/App.tsx +++ b/gui/src/App.tsx @@ -56,7 +56,6 @@ function readStoredTheme(): Theme { export default function App() { const [page, setPageState] = useState(readPageFromHash); - const setPage = (p: Page) => { location.hash = p; setPageState(p); }; const [theme, setTheme] = useState(readStoredTheme); const [runtimeVersion, setRuntimeVersion] = useState(null); const { locale, setLocale } = useI18n(); @@ -68,6 +67,13 @@ export default function App() { return () => window.removeEventListener("hashchange", onHash); }, []); + useEffect(() => { + const nextHash = `#${page}`; + if (window.location.hash !== nextHash) { + window.location.hash = page; + } + }, [page]); + useEffect(() => { const el = document.documentElement; if (theme === "system") { el.removeAttribute("data-theme"); localStorage.removeItem(THEME_KEY); } @@ -112,7 +118,7 @@ export default function App() {