Skip to content

Commit bdfd64a

Browse files
initial public release v0.1.0 under Apache 2.0
0 parents  commit bdfd64a

161 files changed

Lines changed: 25278 additions & 0 deletions

File tree

Some content is hidden

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

.dockerignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Build artifacts
2+
node_modules
3+
dist
4+
coverage
5+
6+
# Environment and secrets
7+
.env
8+
.env.local
9+
.env.*.local
10+
11+
# Logs
12+
*.log
13+
pre-log.json
14+
post-log.json
15+
16+
# Version control and IDE
17+
.git
18+
.gitignore
19+
.internal
20+
.claude
21+
.idea
22+
.vscode
23+
*.swp
24+
.DS_Store
25+
26+
# Tests and dev tooling (not needed at runtime)
27+
tests
28+
examples
29+
bench
30+
scripts
31+
32+
# CI/CD (not needed at runtime)
33+
.github
34+
35+
# Docs (not needed at runtime)
36+
docs
37+
*.md

.env.example

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# =============================================================================
2+
# HARBOR — ENVIRONMENT VARIABLE REFERENCE
3+
# Keys read by core/config/config.ts (validateGlobalConfig +
4+
# resolveStoreTypeConfig). Copy to your deploy env or local .env file.
5+
#
6+
# Convention:
7+
# - Uncommented lines = defaults applied when the var is absent.
8+
# - Commented lines = conditional / optional; set only when needed.
9+
# - "required" means the process exits at startup if the var is absent
10+
# and the relevant backend type is active.
11+
#
12+
# ── Quick index (everything validateGlobalConfig + backends may read) ────────
13+
# Always parsed (defaults shown inline below where uncommented):
14+
# MCP_HOST MCP_PORT MCP_TRANSPORT MCP_TOKEN?
15+
# SERVICES_DIR
16+
# SESSION_IDLE_TTL_MS SESSION_SWEEP_INTERVAL_MS
17+
# AUTH_TOKEN_CACHE_TTL_MS TOKEN_CACHE_TYPE IDEMPOTENCY_TYPE
18+
# SANDBOX_MEMORY_MB SANDBOX_EXECUTE_TIMEOUT_MS SANDBOX_SEARCH_TIMEOUT_MS
19+
# SANDBOX_MAX_API_CALLS SANDBOX_MAX_CONCURRENT_CALLS
20+
# LOG_LEVEL SERVICE_NAME MCP_AGENT_NAME ENVIRONMENT ENABLE_AUDIT
21+
# Conditional — TOKEN_CACHE_TYPE:
22+
# memcache → TOKEN_CACHE_MEMCACHE_HOST PORT (+ optional TIMEOUT_MS)
23+
# couchbase → TOKEN_CACHE_CB_HOST PORT BUCKET USERNAME PASSWORD (+ optional TIMEOUT_MS)
24+
# Conditional — IDEMPOTENCY_TYPE:
25+
# memcache → IDEMPOTENCY_MEMCACHE_HOST PORT (+ optional TIMEOUT_MS)
26+
# couchbase → IDEMPOTENCY_CB_HOST PORT BUCKET USERNAME PASSWORD (+ optional TIMEOUT_MS)
27+
# =============================================================================
28+
29+
# ── MCP server ────────────────────────────────────────────────────────────────
30+
MCP_HOST=127.0.0.1
31+
MCP_PORT=3333
32+
# http | stdio
33+
MCP_TRANSPORT=http
34+
# Required when MCP_TRANSPORT=stdio — static bearer for the stdio client connection
35+
# MCP_TOKEN=
36+
37+
# ── Services directory ────────────────────────────────────────────────────────
38+
# Absolute or relative path to the directory containing per-service subdirectories.
39+
# Each subdirectory must contain a config.json. Defaults to ./services when unset.
40+
# In Docker the image sets this to /app/services automatically.
41+
# SERVICES_DIR=./services
42+
43+
# ── Session (HTTP transport only) ─────────────────────────────────────────────
44+
# Idle MCP session eviction threshold (ms). Default: 1 hour.
45+
SESSION_IDLE_TTL_MS=3600000
46+
# How often the idle-session sweeper runs (ms). Default: 5 min.
47+
SESSION_SWEEP_INTERVAL_MS=300000
48+
49+
# ── Auth — token cache TTL ────────────────────────────────────────────────────
50+
# Upper bound on how long a validated token stays cached. Actual TTL per entry
51+
# = min(token's own expires_in, AUTH_TOKEN_CACHE_TTL_MS). Default: 5 min.
52+
AUTH_TOKEN_CACHE_TTL_MS=300000
53+
54+
# ── Token cache backend (SYSTEM-LEVEL — shared by every service, no per-service override)
55+
# One backend is active for the entire gateway process.
56+
# Valid values: in-memory | memcache | couchbase
57+
TOKEN_CACHE_TYPE=in-memory
58+
59+
# ── TOKEN_CACHE_TYPE=memcache ─────────────────────────────────────────────────
60+
# Prefix: TOKEN_CACHE_MEMCACHE_
61+
# Use when multiple gateway pods share a Memcached cluster for token lookups.
62+
#
63+
# TOKEN_CACHE_MEMCACHE_HOST=memcache.svc.cluster.local # required
64+
# TOKEN_CACHE_MEMCACHE_PORT=11211 # required
65+
# TOKEN_CACHE_MEMCACHE_TIMEOUT_MS=2000 # optional (default: 2000)
66+
67+
# ── TOKEN_CACHE_TYPE=couchbase ────────────────────────────────────────────────
68+
# Prefix: TOKEN_CACHE_CB_ (host, port, bucket, username, password).
69+
# Token cache and idempotency use separate env prefixes so each can target a different cluster.
70+
# Recommended bucket name: mcp-token-cache (bucket TTL ≈ 300 s to match token TTL).
71+
#
72+
# TOKEN_CACHE_CB_HOST=cb-cluster-0.cb-cluster.couchbase.svc.cluster.local # required
73+
# TOKEN_CACHE_CB_PORT=8091 # required (REST/KV port per your deployment)
74+
# TOKEN_CACHE_CB_BUCKET=mcp-token-cache # required — create bucket in Couchbase first
75+
# TOKEN_CACHE_CB_USERNAME= # required — Vault: TOKEN_CACHE_CB_USERNAME
76+
# TOKEN_CACHE_CB_PASSWORD= # required — Vault: TOKEN_CACHE_CB_PASSWORD
77+
# TOKEN_CACHE_CB_TIMEOUT_MS=3000 # optional (default: 3000)
78+
79+
# ── Sandbox (SYSTEM-LEVEL defaults — per-service config.json sandbox block may override)
80+
SANDBOX_MEMORY_MB=64 # V8 isolate memory cap per run (MB)
81+
SANDBOX_EXECUTE_TIMEOUT_MS=8000 # Wall-clock cap for api_execute sandbox (ms; includes awaits)
82+
SANDBOX_SEARCH_TIMEOUT_MS=3000 # Wall-clock cap for search_code / discover_skills (ms)
83+
SANDBOX_MAX_API_CALLS=50 # Max api.request() calls per sandbox run
84+
SANDBOX_MAX_CONCURRENT_CALLS=5 # Max concurrent in-flight requests per run
85+
86+
# ── Idempotency (SYSTEM-LEVEL default — services may override type + TTL in config.json)
87+
# Default is noop (no deduplication). For multi-pod deployments use memcache or couchbase.
88+
# Connection fields (host/port/bucket/credentials) are env-only; per-service config.json
89+
# may only change the type and idempotencyKeyTtlMs.
90+
# Valid values: noop | in-memory | memcache | couchbase
91+
IDEMPOTENCY_TYPE=noop
92+
93+
# ── IDEMPOTENCY_TYPE=memcache ─────────────────────────────────────────────────
94+
# Prefix: IDEMPOTENCY_MEMCACHE_
95+
# Use when multiple gateway pods share a Memcached cluster for request deduplication.
96+
# Token cache may use a different Memcached cluster via TOKEN_CACHE_MEMCACHE_*.
97+
#
98+
# IDEMPOTENCY_MEMCACHE_HOST=memcache.svc.cluster.local # required
99+
# IDEMPOTENCY_MEMCACHE_PORT=11211 # required
100+
# IDEMPOTENCY_MEMCACHE_TIMEOUT_MS=2000 # optional (default: 2000)
101+
102+
# ── IDEMPOTENCY_TYPE=couchbase ────────────────────────────────────────────────
103+
# Prefix: IDEMPOTENCY_CB_
104+
# Recommended bucket name: mcp-idempotency (bucket TTL ≈ 86400 s = 1 day).
105+
#
106+
# IDEMPOTENCY_CB_HOST=cb-cluster-0.cb-cluster.couchbase.svc.cluster.local # required
107+
# IDEMPOTENCY_CB_PORT=8091 # required
108+
# IDEMPOTENCY_CB_BUCKET=mcp-idempotency # required — create bucket in Couchbase first
109+
# IDEMPOTENCY_CB_USERNAME= # required — Vault: IDEMPOTENCY_CB_USERNAME
110+
# IDEMPOTENCY_CB_PASSWORD= # required — Vault: IDEMPOTENCY_CB_PASSWORD
111+
# IDEMPOTENCY_CB_TIMEOUT_MS=3000 # optional (default: 3000)
112+
113+
# ── Observability ─────────────────────────────────────────────────────────────
114+
# fatal | error | warn | info | debug | trace
115+
LOG_LEVEL=info
116+
SERVICE_NAME=harbor-gateway
117+
# Sent as X-Request-Source header to all downstream API calls. Default: mcp-agent.
118+
MCP_AGENT_NAME=mcp-agent
119+
# dev | staging | staging-secondary | canary | prod
120+
# Non-prod environments include caller file:line in logs (pino-caller).
121+
ENVIRONMENT=dev
122+
# Set true in production to log every api_execute call for compliance/audit trails.
123+
ENABLE_AUDIT=false
124+
125+
# ── OAuth 2.1 / RFC 9728 Protected Resource Metadata (optional) ──────────────
126+
# Set HARBOR_RESOURCE_URI to enable the OAuth 2.1 discovery flow.
127+
# When set, Harbor advertises a /.well-known/oauth-protected-resource document
128+
# and includes a WWW-Authenticate header on 401 responses so MCP clients can
129+
# discover where to obtain a token. Clients that already carry a token are
130+
# completely unaffected.
131+
#
132+
# HARBOR_RESOURCE_URI=https://harbor.example.com # required to enable OAuth 2.1 mode
133+
# HARBOR_AUTH_SERVERS=https://auth.example.com # comma-separated list of AS URIs
134+
# HARBOR_SCOPES_SUPPORTED=api:read,api:write # optional: advertised scopes
135+
136+
# ── Per-service config.json ────────────────────────────────────────────────────
137+
# Connection and strategy options for each service live in services/<name>/config.json,
138+
# not in env vars. See docs/configuration.md for the full per-service reference and the
139+
# idempotency merge semantics over the IDEMPOTENCY_* defaults above.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
name: Bug report
3+
about: Report a reproducible bug
4+
labels: bug
5+
---
6+
7+
**Describe the bug**
8+
A clear and concise description of what is wrong.
9+
10+
**To reproduce**
11+
Steps to reproduce the behavior:
12+
1.
13+
2.
14+
3.
15+
16+
**Expected behavior**
17+
What you expected to happen.
18+
19+
**Actual behavior**
20+
What actually happened. Paste relevant log output.
21+
22+
**Environment**
23+
- Harbor version:
24+
- Node version: `node --version`
25+
- OS:
26+
- Transport: `http` / `stdio`
27+
28+
**Additional context**
29+
Any other information that may be relevant.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Feature request
3+
about: Propose a new feature or enhancement
4+
labels: enhancement
5+
---
6+
7+
**Is your feature request related to a problem?**
8+
A clear and concise description of the problem. (e.g. "I can't do X without Y")
9+
10+
**Describe the solution you'd like**
11+
What should be added or changed?
12+
13+
**Describe alternatives you've considered**
14+
Any alternative solutions or features you've considered.
15+
16+
**Additional context**
17+
Any other context, code examples, or mockups.

.github/pull_request_template.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
## Summary
2+
3+
<!-- What does this PR do and why? One paragraph. -->
4+
5+
## Type of change
6+
7+
- [ ] Bug fix
8+
- [ ] New feature
9+
- [ ] Refactor / internal change
10+
- [ ] Documentation
11+
- [ ] Other:
12+
13+
## Test plan
14+
15+
<!-- How did you verify this works? List manual steps, new test files, or edge cases covered. -->
16+
17+
## Checklist
18+
19+
- [ ] `npm run typecheck` passes
20+
- [ ] `npm test` passes (all existing tests green)
21+
- [ ] New tests added for new behavior
22+
- [ ] Apache-2.0 SPDX header on every new `.ts` file
23+
- [ ] No internal company names, hostnames, or credentials introduced
24+
- [ ] CHANGELOG.md updated if this is a user-visible change
25+
- [ ] Layer discipline respected (`runtime/` does not import `adapters/` directly)
26+
27+
## Related issues
28+
29+
Closes #

.github/workflows/ci.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
ci:
9+
runs-on: ubuntu-latest
10+
env:
11+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
12+
13+
steps:
14+
- uses: actions/checkout@v4.2.2
15+
16+
- uses: actions/setup-node@v4.4.0
17+
with:
18+
node-version: '22'
19+
cache: 'npm'
20+
21+
- name: Install dependencies
22+
run: npm ci
23+
24+
- name: Typecheck
25+
run: npm run typecheck
26+
27+
- name: Lint
28+
run: npm run lint
29+
30+
- name: Unit & integration tests
31+
run: npm test
32+
33+
- name: E2E — full suite (MCP tools + OAuth metadata + real JWT via Docker)
34+
run: |
35+
python3 tests/demo_e2e.py --start-services --oauth \
36+
--oauth-resource-uri "http://127.0.0.1:3333" \
37+
--oauth-auth-servers "https://auth.example.com" \
38+
--docker-oauth

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Build output
2+
dist/
3+
4+
# Node
5+
node_modules/
6+
.next/
7+
out/
8+
9+
# Env
10+
.env
11+
.env.local
12+
.env.*.local
13+
14+
# Logs and local tool artifacts
15+
*.log
16+
pre-log.json
17+
post-log.json
18+
bench/*.log
19+
20+
# IDE
21+
.idea/
22+
.vscode/
23+
*.swp
24+
25+
# Claude Code local settings
26+
.claude/
27+
28+
# OS
29+
**/.DS_Store
30+
31+
# Test / coverage
32+
.pytest_cache/
33+
coverage/
34+
35+
# Internal working files — not for public repo
36+
.internal/
37+
reviews/
38+
__pycache__/

.gitleaks.toml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# gitleaks configuration for Harbor
2+
# https://github.com/gitleaks/gitleaks
3+
4+
title = "Harbor gitleaks config"
5+
6+
[allowlist]
7+
description = "Allowlisted demo/test values that are intentionally committed"
8+
9+
# demo-token-123 is the documented example token used in services/*/config.json
10+
# and the getting-started guide. It is not a real credential — see README.md.
11+
regexes = [
12+
"demo-token-123",
13+
]
14+
15+
# Ignore the getting-started doc which also references the demo token by design
16+
paths = [
17+
"docs/getting-started.md",
18+
"docs/service-onboarding.md",
19+
"services/tasks/config.json",
20+
"services/order/config.json",
21+
"services/product/config.json",
22+
]

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22

0 commit comments

Comments
 (0)