mirror of
https://github.com/przeprogramowani/10x-cli.git
synced 2026-09-19 03:30:01 +08:00
docs: wymagania sieciowe dla urządzeń służbowych (allowlist PL+EN) (#53)
* docs: add corporate network allowlist for security/sysadmin teams Polish sysadmin spec plus a machine-readable host list and a source-scan test so new CLI destinations cannot land undocumented. * chore(release): prepare v1.23.1 * docs: rewrite corporate allowlist in sysadmin language (PL+EN) Plain host/port/protocol tables, matching English document, and an allowlist test that covers both language files. * docs: drop localhost from the corporate network allowlist Public DNS names only; the source scan skips IP literals and single-label hosts so local-dev URLs stay out of the sysadmin spec. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,10 @@ prompts, and configs directly into your workspace.
|
||||
|
||||
- **Node 20+** — this is the only runtime dependency.
|
||||
|
||||
Corporate firewall / proxy allowlist (for security and sysadmin teams):
|
||||
Polish [docs/wymagania-sieciowe.md](docs/wymagania-sieciowe.md),
|
||||
English [docs/network-requirements.md](docs/network-requirements.md).
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
{
|
||||
"version": 1,
|
||||
"updated": "2026-09-18",
|
||||
"description": "Hostnames that 10x-cli source may mention or contact. Keep in sync with docs/wymagania-sieciowe.md and docs/network-requirements.md. tests/network-allowlist.test.ts fails when src/ or those docs introduce an unlisted host.",
|
||||
"hosts": [
|
||||
{
|
||||
"hostname": "10x-toolkit-api.przeprogramowani.workers.dev",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "cli_process",
|
||||
"required": true,
|
||||
"inDocs": true,
|
||||
"when": ["login", "every_authenticated_command", "doctor"],
|
||||
"purpose": "Delivery API: auth, membership, catalog, lessons, artifacts, health"
|
||||
},
|
||||
{
|
||||
"hostname": "registry.npmjs.org",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "cli_process",
|
||||
"required": true,
|
||||
"inDocs": true,
|
||||
"when": ["install", "update_check"],
|
||||
"purpose": "Public npm registry for @przeprogramowani/10x-cli; doctor version lookup"
|
||||
},
|
||||
{
|
||||
"hostname": "10xbench.ai",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "cli_process",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["bench"],
|
||||
"purpose": "Public leaderboard JSON for `10x bench`"
|
||||
},
|
||||
{
|
||||
"hostname": "github.com",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "cli_process",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["bench_kit", "optional_binary_install"],
|
||||
"purpose": "git clone of 10x-bench-kit; optional GitHub Releases binary download"
|
||||
},
|
||||
{
|
||||
"hostname": "objects.githubusercontent.com",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "browser",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["optional_binary_install"],
|
||||
"purpose": "Unconfirmed GitHub Releases asset CDN"
|
||||
},
|
||||
{
|
||||
"hostname": "release-assets.githubusercontent.com",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "browser",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["optional_binary_install"],
|
||||
"purpose": "Unconfirmed GitHub Releases asset CDN"
|
||||
},
|
||||
{
|
||||
"hostname": "toolkit.przeprogramowani.pl",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "browser",
|
||||
"required": true,
|
||||
"inDocs": true,
|
||||
"when": ["login_email"],
|
||||
"purpose": "Magic-link callback opened in the user's browser"
|
||||
},
|
||||
{
|
||||
"hostname": "10xdevs.pl",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "browser",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["enrollment_hint"],
|
||||
"purpose": "Enrollment URL printed in error hints; CLI does not fetch it"
|
||||
},
|
||||
{
|
||||
"hostname": "app.circle.so",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "browser",
|
||||
"required": false,
|
||||
"inDocs": true,
|
||||
"when": ["login_circle_human"],
|
||||
"purpose": "Circle web app so the user can open the login DM; CLI process does not connect"
|
||||
},
|
||||
{
|
||||
"hostname": "git-scm.com",
|
||||
"port": 443,
|
||||
"protocol": "https",
|
||||
"calledBy": "documentation_only",
|
||||
"required": false,
|
||||
"inDocs": false,
|
||||
"when": ["bench_kit"],
|
||||
"purpose": "Install-git hint in a bench-kit error message; CLI does not fetch it"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
# 10x-cli network requirements
|
||||
|
||||
Polish: [wymagania-sieciowe.md](wymagania-sieciowe.md).
|
||||
Machine-readable host list: [network-allowlist.json](network-allowlist.json).
|
||||
|
||||
10x-cli (`@przeprogramowani/10x-cli`) signs a 10xDevs course user in and writes lesson files to disk. It does not open a listening port. It does not upload project source code.
|
||||
|
||||
---
|
||||
|
||||
## Allowlist
|
||||
|
||||
Every row: HTTPS, TCP 443, from the device.
|
||||
|
||||
### Required for course use
|
||||
|
||||
| Host | Port | Protocol | Purpose | Without it |
|
||||
|------|------|----------|---------|------------|
|
||||
| `10x-toolkit-api.przeprogramowani.workers.dev` | 443 | HTTPS | Login, token refresh, lesson list and content, `10x doctor` | `10x auth`, `list`, `get`, `sync` fail; `doctor` reports the API unreachable |
|
||||
| `registry.npmjs.org` | 443 | HTTPS | Install and update `@przeprogramowani/10x-cli` (`npx` / `npm install -g`) | npm install and upgrade fail. `10x doctor` still runs — it skips the version check |
|
||||
| `toolkit.przeprogramowani.pl` | 443 | HTTPS | Login email link (`/auth/callback`) opened in the browser | Email login (`10x auth`) does not finish after the user clicks the link |
|
||||
|
||||
`10x-cli` calls the API only at `10x-toolkit-api.przeprogramowani.workers.dev`. `toolkit.przeprogramowani.pl` is browser-only, for email login.
|
||||
|
||||
### Browser — Circle login
|
||||
|
||||
| Host | Port | Protocol | Purpose | Without it |
|
||||
|------|------|----------|---------|------------|
|
||||
| `10x-toolkit-api.przeprogramowani.workers.dev` | 443 | HTTPS | Approval page from the Circle message | `10x auth --method circle` waits until the link expires |
|
||||
| `app.circle.so` | 443 | HTTPS | Reading the Circle message that contains the link | The user cannot open the message (the `10x` process does not connect here) |
|
||||
|
||||
### Optional
|
||||
|
||||
| Host | Port | Protocol | Purpose | Without it |
|
||||
|------|------|----------|---------|------------|
|
||||
| `10xbench.ai` | 443 | HTTPS | Model leaderboard (`10x bench`) | `10x bench` fails; lesson download is unchanged |
|
||||
| `github.com` | 443 | HTTPS | `git clone` of the `10x-bench-kit` template; optional GitHub Releases binary | `10x bench-kit` cannot fetch the template. Course `get` / `sync` unchanged |
|
||||
| `objects.githubusercontent.com` | 443 | HTTPS | GitHub Releases asset CDN (unconfirmed) | Downloading the standalone binary from Releases may fail |
|
||||
| `release-assets.githubusercontent.com` | 443 | HTTPS | GitHub Releases asset CDN (unconfirmed) | same |
|
||||
| `10xdevs.pl` | 443 | HTTPS | Course enrolment site (error-message hint only) | No effect on the CLI |
|
||||
|
||||
`10x bench-kit` may also run `git ls-remote` against the `origin` of the repo where the command was invoked — that host is whatever the user’s git config already uses.
|
||||
|
||||
---
|
||||
|
||||
## Protocol and TLS
|
||||
|
||||
- HTTPS / TLS, TCP 443. Login: `POST`/`GET` and repeated HTTP (every 2 s, up to 5 min). No WebSocket or SSE.
|
||||
- API and 10xbench timeout: 30 s. `doctor` → API: 5 s. `doctor` → npm: 2 s.
|
||||
- User-Agent: `10x-cli`.
|
||||
- The CLI does not listen on any port.
|
||||
|
||||
Corporate TLS inspection (custom CA):
|
||||
|
||||
| Setting | Fact |
|
||||
|---------|------|
|
||||
| `NODE_EXTRA_CA_CERTS` | Node.js appends a PEM CA file. Applies when `10x` runs on Node (npm install). |
|
||||
| OS certificate store | The CLI does not enable `--use-system-ca`. |
|
||||
| `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` | `npm` / `npx` usually honour these. Node 20 `fetch` (CLI minimum) does not unless `NODE_USE_ENV_PROXY=1` (Node 24+). On Node 20–22, proxy for `10x auth` / `10x get` is unconfirmed. |
|
||||
| Standalone binary | Different runtime from Node. `NODE_EXTRA_CA_CERTS` / `HTTPS_PROXY`: unconfirmed. |
|
||||
|
||||
If inspection breaks TLS: point `NODE_EXTRA_CA_CERTS` at the corporate root, or disable inspection for the hosts in the tables.
|
||||
|
||||
---
|
||||
|
||||
## On the device
|
||||
|
||||
| Component | Required |
|
||||
|-----------|----------|
|
||||
| Node.js ≥ 20 | Yes for npm/npx install |
|
||||
| npm / npx | Yes for npm install. No for the standalone binary |
|
||||
| git | `10x bench-kit` only |
|
||||
| Docker / Podman | Not for the CLI |
|
||||
| OS | macOS, Linux, Windows |
|
||||
|
||||
Session tokens (email, access/refresh JWT, expiry) — not a Circle password:
|
||||
|
||||
| OS | Directory | Files | Permissions (POSIX) |
|
||||
|----|-----------|-------|---------------------|
|
||||
| macOS / Linux | `$XDG_CONFIG_HOME/10x-cli` or `~/.config/10x-cli` | `auth.json`, `config.json` | directory `0700`, `auth.json` `0600` |
|
||||
| Windows | `%APPDATA%\10x-cli` | same files | — |
|
||||
|
||||
Lesson files are written into the user’s project directory (for example `.claude/skills/`, `CLAUDE.md`).
|
||||
|
||||
---
|
||||
|
||||
## Data leaving the device
|
||||
|
||||
| Data | When |
|
||||
|------|------|
|
||||
| Email address | `10x auth`; stored in `auth.json` |
|
||||
| JWT access + refresh | Login and every API call (`Authorization: Bearer`) |
|
||||
| Hostname and a short OS string | Start of `10x auth --method circle` only |
|
||||
| User-Agent `10x-cli` | Every CLI request |
|
||||
| Package-version GET (no token) | `10x doctor` → `registry.npmjs.org` |
|
||||
| Public leaderboard JSON (no token) | `10x bench` |
|
||||
|
||||
Project source code is not uploaded.
|
||||
|
||||
---
|
||||
|
||||
## AI coding tools (separate allowlist)
|
||||
|
||||
10x-cli does not call Anthropic, OpenAI, Google, or OpenRouter. It writes files for the chosen `--tool`. Model traffic is that tool’s traffic.
|
||||
|
||||
| `--tool` | Vendor network requirements |
|
||||
|----------|------------------------------|
|
||||
| `claude-code` | [Claude Code — enterprise network](https://docs.claude.com/en/docs/claude-code/network-config) |
|
||||
| `cursor` | [Cursor — network configuration](https://cursor.com/docs/enterprise/network-configuration) |
|
||||
| `copilot` | [GitHub Copilot allowlist](https://docs.github.com/copilot/reference/copilot-allowlist-reference) |
|
||||
| `codex` | [Codex — network](https://developers.openai.com/codex/agent-approvals-security/) — full local-CLI host list: confirm with OpenAI |
|
||||
| `gemini` | [Gemini Code Assist network access](https://developers.google.com/gemini-code-assist/docs/network-access) — confirm for Gemini CLI |
|
||||
| `kiro` | [Kiro — firewalls and proxies](https://kiro.dev/docs/web/firewalls/) |
|
||||
| `devin-desktop` (`windsurf` alias) | [Devin Desktop — domains](https://docs.devin.ai/desktop/troubleshooting/windsurf-common-issues) |
|
||||
| `generic` | No vendor |
|
||||
|
||||
---
|
||||
|
||||
## How to verify
|
||||
|
||||
```bash
|
||||
curl -I --max-time 10 https://10x-toolkit-api.przeprogramowani.workers.dev/health
|
||||
curl -I --max-time 10 https://registry.npmjs.org/@przeprogramowani/10x-cli/latest
|
||||
curl -I --max-time 10 https://toolkit.przeprogramowani.pl/auth/callback
|
||||
curl -I --max-time 10 https://10xbench.ai/api/leaderboard.json
|
||||
curl -I --max-time 10 https://github.com/przeprogramowani/10x-bench-kit
|
||||
```
|
||||
|
||||
TLS handshake matters (HTTP 200 is not required). On the device: `10x doctor`.
|
||||
|
||||
| Blocked host | CLI message |
|
||||
|--------------|-------------|
|
||||
| API | `Could not reach the 10x-toolkit API.` |
|
||||
| `doctor`, 5 s timeout | `{url} did not respond within 5s.` |
|
||||
| `doctor`, other network error | `{url} is unreachable.` |
|
||||
| npm (does not fail `doctor`) | `10x-cli {version} (update check skipped).` |
|
||||
| `10x bench` | `Could not reach 10xbench.ai.` |
|
||||
| `10x bench-kit` | `Could not download the template from https://github.com/przeprogramowani/10x-bench-kit.` |
|
||||
| bad certificate / intercept | `network_error` plus the runtime message |
|
||||
|
||||
Exit codes: `0` success, `1` error, `2` usage, `3` auth required, `4` forbidden, `5` not found. `doctor` with a dead API: **78**.
|
||||
|
||||
---
|
||||
|
||||
## Keeping this list current
|
||||
|
||||
Canonical hosts: [network-allowlist.json](network-allowlist.json). `tests/network-allowlist.test.ts` fails if `src/` or this document / the Polish version introduce a host outside the list. A new host = the same PR: JSON + EN + PL.
|
||||
@@ -3,6 +3,7 @@
|
||||
## Requirements
|
||||
|
||||
- **Node 20+** — the only runtime dependency on all platforms.
|
||||
- Corporate network allowlist: Polish [wymagania-sieciowe.md](../wymagania-sieciowe.md), English [network-requirements.md](../network-requirements.md).
|
||||
|
||||
## Supported platforms
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
# Wymagania sieciowe 10x-cli
|
||||
|
||||
English: [network-requirements.md](network-requirements.md).
|
||||
Machine-readable host list: [network-allowlist.json](network-allowlist.json).
|
||||
|
||||
10x-cli (`@przeprogramowani/10x-cli`) loguje użytkownika kursu 10xDevs i zapisuje materiały lekcji na dysk. Nie otwiera portu nasłuchującego. Nie wysyła kodu źródłowego projektu.
|
||||
|
||||
---
|
||||
|
||||
## Allowlista
|
||||
|
||||
Wszystkie wpisy: HTTPS, TCP 443, z urządzenia.
|
||||
|
||||
### Wymagane do kursu
|
||||
|
||||
| Host | Port | Protokół | Cel | Bez tego |
|
||||
|------|------|----------|-----|----------|
|
||||
| `10x-toolkit-api.przeprogramowani.workers.dev` | 443 | HTTPS | Logowanie, odświeżanie tokenu, lista i treść lekcji, `10x doctor` | Nie działa `10x auth`, `list`, `get`, `sync`; `doctor` zgłasza, że API jest nieosiągalne |
|
||||
| `registry.npmjs.org` | 443 | HTTPS | Instalacja i aktualizacja `@przeprogramowani/10x-cli` (`npx` / `npm install -g`) | Nie da się zainstalować ani zaktualizować pakietu npm. `10x doctor` nadal działa — pomija sprawdzenie wersji |
|
||||
| `toolkit.przeprogramowani.pl` | 443 | HTTPS | Link z e-maila logowania (`/auth/callback`) otwierany w przeglądarce | Logowanie mailem (`10x auth`) nie dokończy się po kliknięciu linku |
|
||||
|
||||
`10x-cli` woła API wyłącznie na `10x-toolkit-api.przeprogramowani.workers.dev`. `toolkit.przeprogramowani.pl` jest tylko dla przeglądarki przy logowaniu mailem.
|
||||
|
||||
### Przeglądarka — logowanie Circle
|
||||
|
||||
| Host | Port | Protokół | Cel | Bez tego |
|
||||
|------|------|----------|-----|----------|
|
||||
| `10x-toolkit-api.przeprogramowani.workers.dev` | 443 | HTTPS | Strona zatwierdzenia z wiadomości Circle | `10x auth --method circle` czeka, aż link wygaśnie |
|
||||
| `app.circle.so` | 443 | HTTPS | Odczyt wiadomości Circle z linkiem | Użytkownik nie otworzy wiadomości (proces `10x` nie łączy się z tym hostem) |
|
||||
|
||||
### Opcjonalne
|
||||
|
||||
| Host | Port | Protokół | Cel | Bez tego |
|
||||
|------|------|----------|-----|----------|
|
||||
| `10xbench.ai` | 443 | HTTPS | Ranking modeli (`10x bench`) | `10x bench` nie działa; pobieranie lekcji bez zmian |
|
||||
| `github.com` | 443 | HTTPS | `git clone` szablonu `10x-bench-kit`; opcjonalny binary z GitHub Releases | `10x bench-kit` nie pobierze szablonu. Kurs (`get` / `sync`) bez zmian |
|
||||
| `objects.githubusercontent.com` | 443 | HTTPS | CDN assetów GitHub Releases (do potwierdzenia) | Pobranie standalone binary z Releases może się nie udać |
|
||||
| `release-assets.githubusercontent.com` | 443 | HTTPS | CDN assetów GitHub Releases (do potwierdzenia) | j.w. |
|
||||
| `10xdevs.pl` | 443 | HTTPS | Strona zapisu na kurs (tylko w komunikacie błędu) | Brak wpływu na CLI |
|
||||
|
||||
`10x bench-kit` może też wywołać `git ls-remote` wobec `origin` repozytorium, w którym uruchomiono komendę — to dowolny host z konfiguracji git użytkownika.
|
||||
|
||||
---
|
||||
|
||||
## Protokół i TLS
|
||||
|
||||
- HTTPS / TLS, TCP 443. Logowanie: `POST`/`GET` i powtarzany HTTP (co 2 s, do 5 min). Brak WebSocket i SSE.
|
||||
- Timeout API i 10xbench: 30 s. `doctor` → API: 5 s. `doctor` → npm: 2 s.
|
||||
- User-Agent: `10x-cli`.
|
||||
- CLI nie nasłuchuje na żadnym porcie.
|
||||
|
||||
Przy korporacyjnym TLS inspection (własny CA):
|
||||
|
||||
| Ustawienie | Fakt |
|
||||
|------------|------|
|
||||
| `NODE_EXTRA_CA_CERTS` | Node.js doda plik PEM z CA. Działa, gdy `10x` uruchamia Node (instalacja npm). |
|
||||
| Magazyn CA systemu | CLI nie włącza `--use-system-ca`. |
|
||||
| `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` | `npm` / `npx` zwykle je honorują. `fetch` w Node 20 (minimum CLI) ich nie używa bez `NODE_USE_ENV_PROXY=1` (Node 24+). Na Node 20–22 proxy dla `10x auth` / `10x get`: do potwierdzenia. |
|
||||
| Standalone binary | Inny runtime niż Node. `NODE_EXTRA_CA_CERTS` / `HTTPS_PROXY`: do potwierdzenia. |
|
||||
|
||||
Jeśli inspection psuje TLS: wskaż korporacyjny root w `NODE_EXTRA_CA_CERTS` albo wyłącz inspection dla hostów z tabeli.
|
||||
|
||||
---
|
||||
|
||||
## Na urządzeniu
|
||||
|
||||
| Składnik | Wymagane |
|
||||
|----------|----------|
|
||||
| Node.js ≥ 20 | Tak przy instalacji npm/npx |
|
||||
| npm / npx | Tak przy instalacji z npm. Nie przy standalone binary |
|
||||
| git | Tylko `10x bench-kit` |
|
||||
| Docker / Podman | Nie dla CLI |
|
||||
| System | macOS, Linux, Windows |
|
||||
|
||||
Tokeny sesji (e-mail, access/refresh JWT, data ważności) — nie hasło do Circle:
|
||||
|
||||
| System | Katalog | Pliki | Uprawnienia (POSIX) |
|
||||
|--------|---------|-------|---------------------|
|
||||
| macOS / Linux | `$XDG_CONFIG_HOME/10x-cli` lub `~/.config/10x-cli` | `auth.json`, `config.json` | katalog `0700`, `auth.json` `0600` |
|
||||
| Windows | `%APPDATA%\10x-cli` | te same | — |
|
||||
|
||||
Materiały lekcji zapisują się w katalogu projektu użytkownika (np. `.claude/skills/`, `CLAUDE.md`).
|
||||
|
||||
---
|
||||
|
||||
## Dane wychodzące z urządzenia
|
||||
|
||||
| Dane | Kiedy |
|
||||
|------|-------|
|
||||
| Adres e-mail | `10x auth`; zapis w `auth.json` |
|
||||
| JWT access + refresh | Logowanie i każde wywołanie API (`Authorization: Bearer`) |
|
||||
| Hostname i krótki opis OS | Tylko start `10x auth --method circle` |
|
||||
| User-Agent `10x-cli` | Każde żądanie CLI |
|
||||
| GET wersji pakietu (bez tokenu) | `10x doctor` → `registry.npmjs.org` |
|
||||
| Publiczny JSON rankingu (bez tokenu) | `10x bench` |
|
||||
|
||||
Kod źródłowy projektu nie jest wysyłany.
|
||||
|
||||
---
|
||||
|
||||
## Narzędzia AI (osobna allowlista)
|
||||
|
||||
10x-cli nie woła Anthropic, OpenAI, Google ani OpenRouter. Zapisuje pliki pod wybrane `--tool`. Ruch modelu to ruch tego narzędzia.
|
||||
|
||||
| `--tool` | Wymagania sieciowe dostawcy |
|
||||
|----------|------------------------------|
|
||||
| `claude-code` | [Claude Code — enterprise network](https://docs.claude.com/en/docs/claude-code/network-config) |
|
||||
| `cursor` | [Cursor — network configuration](https://cursor.com/docs/enterprise/network-configuration) |
|
||||
| `copilot` | [GitHub Copilot allowlist](https://docs.github.com/copilot/reference/copilot-allowlist-reference) |
|
||||
| `codex` | [Codex — network](https://developers.openai.com/codex/agent-approvals-security/) — pełna lista hostów lokalnego CLI: do potwierdzenia u OpenAI |
|
||||
| `gemini` | [Gemini Code Assist network access](https://developers.google.com/gemini-code-assist/docs/network-access) — do potwierdzenia dla Gemini CLI |
|
||||
| `kiro` | [Kiro — firewalls and proxies](https://kiro.dev/docs/web/firewalls/) |
|
||||
| `devin-desktop` (alias `windsurf`) | [Devin Desktop — domains](https://docs.devin.ai/desktop/troubleshooting/windsurf-common-issues) |
|
||||
| `generic` | Brak dostawcy |
|
||||
|
||||
---
|
||||
|
||||
## Weryfikacja
|
||||
|
||||
```bash
|
||||
curl -I --max-time 10 https://10x-toolkit-api.przeprogramowani.workers.dev/health
|
||||
curl -I --max-time 10 https://registry.npmjs.org/@przeprogramowani/10x-cli/latest
|
||||
curl -I --max-time 10 https://toolkit.przeprogramowani.pl/auth/callback
|
||||
curl -I --max-time 10 https://10xbench.ai/api/leaderboard.json
|
||||
curl -I --max-time 10 https://github.com/przeprogramowani/10x-bench-kit
|
||||
```
|
||||
|
||||
Ważne jest zestawienie TLS (niekoniecznie HTTP 200). Na urządzeniu: `10x doctor`.
|
||||
|
||||
| Blokada | Komunikat CLI |
|
||||
|---------|----------------|
|
||||
| API | `Could not reach the 10x-toolkit API.` |
|
||||
| `doctor`, timeout 5 s | `{url} did not respond within 5s.` |
|
||||
| `doctor`, inny błąd sieci | `{url} is unreachable.` |
|
||||
| npm (nie blokuje `doctor`) | `10x-cli {wersja} (update check skipped).` |
|
||||
| `10x bench` | `Could not reach 10xbench.ai.` |
|
||||
| `10x bench-kit` | `Could not download the template from https://github.com/przeprogramowani/10x-bench-kit.` |
|
||||
| zły certyfikat / intercept | `network_error` i komunikat runtime |
|
||||
|
||||
Kody wyjścia: `0` sukces, `1` błąd, `2` użycie, `3` brak sesji, `4` brak uprawnień, `5` nie znaleziono. `doctor` przy martwym API: **78**.
|
||||
|
||||
---
|
||||
|
||||
## Aktualizacja tej listy
|
||||
|
||||
Kanoniczne hosty: [network-allowlist.json](network-allowlist.json). Test `tests/network-allowlist.test.ts` failuje, gdy `src/` albo ten dokument / wersja angielska dodadzą hosta spoza listy. Nowy host = ten sam PR: JSON + PL + EN.
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@przeprogramowani/10x-cli",
|
||||
"version": "1.23.0",
|
||||
"version": "1.23.1",
|
||||
"description": "Open-source CLI for 10xDevs course content",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Fails when src/ or the sysadmin docs mention a hostname that is not listed
|
||||
* in docs/network-allowlist.json. Hosts with inDocs: true must appear in both
|
||||
* the Polish and English documents.
|
||||
*/
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { readdirSync, readFileSync, statSync } from "node:fs";
|
||||
import { join, relative, resolve } from "node:path";
|
||||
|
||||
const ROOT = resolve(import.meta.dir, "..");
|
||||
const SRC = join(ROOT, "src");
|
||||
const ALLOWLIST_PATH = join(ROOT, "docs/network-allowlist.json");
|
||||
const DOC_PATHS = [
|
||||
"docs/wymagania-sieciowe.md",
|
||||
"docs/network-requirements.md",
|
||||
] as const;
|
||||
const HOST_RE = /https?:\/\/([a-zA-Z0-9.-]+)/g;
|
||||
/** Vendor documentation links in the AI-tool table — not 10x-cli destinations. */
|
||||
const VENDOR_DOC_HOSTS = new Set([
|
||||
"docs.claude.com",
|
||||
"cursor.com",
|
||||
"docs.github.com",
|
||||
"developers.openai.com",
|
||||
"developers.google.com",
|
||||
"kiro.dev",
|
||||
"docs.devin.ai",
|
||||
]);
|
||||
|
||||
interface AllowlistHost {
|
||||
hostname: string;
|
||||
inDocs?: boolean;
|
||||
}
|
||||
|
||||
interface AllowlistFile {
|
||||
version: number;
|
||||
hosts: AllowlistHost[];
|
||||
}
|
||||
|
||||
function walkTsFiles(dir: string): string[] {
|
||||
const out: string[] = [];
|
||||
for (const name of readdirSync(dir)) {
|
||||
const path = join(dir, name);
|
||||
const st = statSync(path);
|
||||
if (st.isDirectory()) out.push(...walkTsFiles(path));
|
||||
else if (name.endsWith(".ts")) out.push(path);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Drop block comments, then line comments that are not inside http(s)://. */
|
||||
function stripComments(source: string): string {
|
||||
const withoutBlocks = source.replace(/\/\*[\s\S]*?\*\//g, " ");
|
||||
return withoutBlocks
|
||||
.split("\n")
|
||||
.map((line) => {
|
||||
let i = 0;
|
||||
while (i < line.length) {
|
||||
if (line.startsWith("https://", i)) {
|
||||
i += "https://".length;
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("http://", i)) {
|
||||
i += "http://".length;
|
||||
continue;
|
||||
}
|
||||
if (line[i] === "/" && line[i + 1] === "/") return line.slice(0, i);
|
||||
i += 1;
|
||||
}
|
||||
return line;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function hostsInText(text: string): Set<string> {
|
||||
const found = new Set<string>();
|
||||
HOST_RE.lastIndex = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = HOST_RE.exec(text)) !== null) {
|
||||
const host = match[1]?.replace(/\.+$/, "");
|
||||
if (host) found.add(host);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/** Allowlist only public DNS names (a dot, not an IP literal). */
|
||||
function isPublicHostname(host: string): boolean {
|
||||
if (!host.includes(".")) return false;
|
||||
if (/^\d{1,3}(?:\.\d{1,3}){3}$/.test(host)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function hostsInSource(): Map<string, string[]> {
|
||||
const found = new Map<string, string[]>();
|
||||
for (const file of walkTsFiles(SRC)) {
|
||||
const text = stripComments(readFileSync(file, "utf8"));
|
||||
for (const host of hostsInText(text)) {
|
||||
if (!isPublicHostname(host)) continue;
|
||||
const rel = relative(ROOT, file);
|
||||
const list = found.get(host) ?? [];
|
||||
if (!list.includes(rel)) list.push(rel);
|
||||
found.set(host, list);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
describe("docs/network-allowlist.json", () => {
|
||||
const raw = JSON.parse(readFileSync(ALLOWLIST_PATH, "utf8")) as AllowlistFile;
|
||||
const listed = new Set(raw.hosts.map((h) => h.hostname));
|
||||
const inDocs = raw.hosts.filter((h) => h.inDocs).map((h) => h.hostname);
|
||||
const docTexts = Object.fromEntries(
|
||||
DOC_PATHS.map((path) => [path, readFileSync(join(ROOT, path), "utf8")]),
|
||||
);
|
||||
|
||||
it("is a versioned host list", () => {
|
||||
expect(raw.version).toBe(1);
|
||||
expect(raw.hosts.length).toBeGreaterThan(0);
|
||||
expect(listed.has("10x-toolkit-api.przeprogramowani.workers.dev")).toBe(true);
|
||||
expect(listed.has("registry.npmjs.org")).toBe(true);
|
||||
});
|
||||
|
||||
it("lists every public hostname referenced from src/", () => {
|
||||
const missing: string[] = [];
|
||||
for (const [host, files] of hostsInSource()) {
|
||||
if (!listed.has(host)) missing.push(`${host} (${files.join(", ")})`);
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it("lists every non-vendor hostname referenced from both sysadmin docs", () => {
|
||||
const missing: string[] = [];
|
||||
for (const path of DOC_PATHS) {
|
||||
const text = docTexts[path] ?? "";
|
||||
for (const host of hostsInText(text)) {
|
||||
if (!isPublicHostname(host) || VENDOR_DOC_HOSTS.has(host)) continue;
|
||||
if (!listed.has(host)) missing.push(`${host} (${path})`);
|
||||
}
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it("requires inDocs hosts in both the Polish and English documents", () => {
|
||||
const missing: string[] = [];
|
||||
for (const path of DOC_PATHS) {
|
||||
const text = docTexts[path] ?? "";
|
||||
for (const host of inDocs) {
|
||||
if (!text.includes(host)) missing.push(`${host} missing from ${path}`);
|
||||
}
|
||||
}
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user