mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-18 01:34:00 -05:00
Add monorepo sync configuration and workflows (#117)
This commit is contained in:
96
.github/workflows/deploy-core-api.yml
vendored
Normal file
96
.github/workflows/deploy-core-api.yml
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
name: Deploy core-api to Railway
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'services/core-api/**'
|
||||||
|
- '.github/workflows/deploy-core-api.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
SERVICE_KEY: core-api
|
||||||
|
SYNC_CONFIG: infra/github/sync-config.yml
|
||||||
|
steps:
|
||||||
|
- name: Checkout monorepo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Load service config
|
||||||
|
id: cfg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python - <<'PY'
|
||||||
|
import yaml, os
|
||||||
|
key = os.environ['SERVICE_KEY']
|
||||||
|
with open(os.environ['SYNC_CONFIG'], 'r') as f:
|
||||||
|
cfg = yaml.safe_load(f)
|
||||||
|
for section in ('services', 'apps', 'docs'):
|
||||||
|
if section in cfg and key in cfg[section]:
|
||||||
|
data = cfg[section][key]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise SystemExit(f"Service {key} not found in config")
|
||||||
|
print(f"monorepo_path={data['monorepo_path']}")
|
||||||
|
PY | tee /tmp/svc_env
|
||||||
|
while IFS='=' read -r name value; do
|
||||||
|
echo "$name=$value" >> "$GITHUB_OUTPUT"
|
||||||
|
done < /tmp/svc_env
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Install service dependencies (placeholder)
|
||||||
|
working-directory: ${{ steps.cfg.outputs.monorepo_path }}
|
||||||
|
run: |
|
||||||
|
if [ -f requirements.txt ]; then
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -r requirements.txt
|
||||||
|
else
|
||||||
|
echo "No requirements.txt; skipping install"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Run service tests (placeholder)
|
||||||
|
working-directory: ${{ steps.cfg.outputs.monorepo_path }}
|
||||||
|
run: |
|
||||||
|
if [ -d tests ]; then
|
||||||
|
pytest --maxfail=1 --disable-warnings -q
|
||||||
|
else
|
||||||
|
echo "No tests directory; skipping"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Deploy to Railway
|
||||||
|
working-directory: ${{ steps.cfg.outputs.monorepo_path }}
|
||||||
|
env:
|
||||||
|
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ -z "$RAILWAY_TOKEN" ]; then
|
||||||
|
echo "RAILWAY_TOKEN is required" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Replace this with the service-specific Railway command
|
||||||
|
railway up --service core-api --yes
|
||||||
|
|
||||||
|
- name: Post-deploy healthcheck
|
||||||
|
env:
|
||||||
|
CORE_API_HEALTHCHECK_URL: ${{ secrets.CORE_API_HEALTHCHECK_URL }}
|
||||||
|
run: |
|
||||||
|
if [ -z "$CORE_API_HEALTHCHECK_URL" ]; then
|
||||||
|
echo "CORE_API_HEALTHCHECK_URL not provided; skipping check"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
status=$(curl -s -o /dev/null -w "%{http_code}" "$CORE_API_HEALTHCHECK_URL/health")
|
||||||
|
if [ "$status" != "200" ]; then
|
||||||
|
echo "Healthcheck failed with status $status" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Document environment expectations
|
||||||
|
run: |
|
||||||
|
echo "Expected env vars: CORE_API_DATABASE_URL, CORE_API_SECRET_KEY, CORE_API_ALLOWED_ORIGINS" \
|
||||||
|
"(see infra/railway/ENVIRONMENT_GUIDE.md)"
|
||||||
118
.github/workflows/sync-core-api.yml
vendored
Normal file
118
.github/workflows/sync-core-api.yml
vendored
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
name: Sync core-api to mirror
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
paths:
|
||||||
|
- 'services/core-api/**'
|
||||||
|
- 'infra/github/sync-config.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
sync:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
SERVICE_KEY: core-api
|
||||||
|
SYNC_CONFIG: infra/github/sync-config.yml
|
||||||
|
SYNC_TOKEN: ${{ secrets.BR_OS_SYNC_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout monorepo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Load service config
|
||||||
|
id: cfg
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python - <<'PY'
|
||||||
|
import json, yaml, os
|
||||||
|
|
||||||
|
key = os.environ['SERVICE_KEY']
|
||||||
|
with open(os.environ['SYNC_CONFIG'], 'r') as f:
|
||||||
|
cfg = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# service can live under services/apps/docs namespaces; search all
|
||||||
|
for section in ('services', 'apps', 'docs'):
|
||||||
|
if section in cfg and key in cfg[section]:
|
||||||
|
data = cfg[section][key]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise SystemExit(f"Service {key} not found in config")
|
||||||
|
|
||||||
|
for output_key, output_value in (
|
||||||
|
('monorepo_path', data['monorepo_path']),
|
||||||
|
('target_repo', data['target_repo']),
|
||||||
|
('target_branch', data.get('target_branch', 'main')),
|
||||||
|
('force_push', str(data.get('force_push', True)).lower()),
|
||||||
|
):
|
||||||
|
print(f"{output_key}={output_value}")
|
||||||
|
PY | tee /tmp/svc_env
|
||||||
|
while IFS='=' read -r name value; do
|
||||||
|
echo "$name=$value" >> "$GITHUB_OUTPUT"
|
||||||
|
done < /tmp/svc_env
|
||||||
|
|
||||||
|
- name: Export service directory
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/export
|
||||||
|
rsync -av --delete "${{ steps.cfg.outputs.monorepo_path }}/" /tmp/export/
|
||||||
|
|
||||||
|
- name: Clone target repository
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ env.SYNC_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
echo "BR_OS_SYNC_TOKEN is required" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git clone "https://${TOKEN}@github.com/${{ steps.cfg.outputs.target_repo }}.git" /tmp/target
|
||||||
|
|
||||||
|
- name: Prepare mirror working tree
|
||||||
|
working-directory: /tmp/target
|
||||||
|
run: |
|
||||||
|
shopt -s dotglob
|
||||||
|
rm -rf -- * .[!.]* ..?*
|
||||||
|
shopt -u dotglob
|
||||||
|
mkdir -p .
|
||||||
|
rsync -av --delete /tmp/export/ ./
|
||||||
|
|
||||||
|
- name: Write sync status
|
||||||
|
working-directory: /tmp/target
|
||||||
|
run: |
|
||||||
|
cat <<'STATUS' > sync-status.md
|
||||||
|
# Sync Status
|
||||||
|
|
||||||
|
- Source repo: blackboxprogramming/BlackRoad-Operating-System
|
||||||
|
- Source path: ${{ steps.cfg.outputs.monorepo_path }}
|
||||||
|
- Source commit: ${{ github.sha }}
|
||||||
|
- Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||||
|
STATUS
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
working-directory: /tmp/target
|
||||||
|
run: |
|
||||||
|
git status
|
||||||
|
if git status --porcelain | grep .; then
|
||||||
|
git config user.name "blackroad-os-bot"
|
||||||
|
git config user.email "blackroad-os-bot@users.noreply.github.com"
|
||||||
|
git add .
|
||||||
|
git commit -m "Sync from BlackRoad-Operating-System: ${{ env.SERVICE_KEY }} @ ${{ github.sha }}"
|
||||||
|
else
|
||||||
|
echo "No changes to sync"
|
||||||
|
echo "skip_push=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
id: commit
|
||||||
|
|
||||||
|
- name: Push mirror
|
||||||
|
if: steps.commit.outputs.skip_push != 'true'
|
||||||
|
working-directory: /tmp/target
|
||||||
|
env:
|
||||||
|
FORCE_PUSH: ${{ steps.cfg.outputs.force_push }}
|
||||||
|
run: |
|
||||||
|
if [ "$FORCE_PUSH" = "true" ]; then
|
||||||
|
git push origin "HEAD:${{ steps.cfg.outputs.target_branch }}" --force
|
||||||
|
else
|
||||||
|
git pull --rebase origin "${{ steps.cfg.outputs.target_branch }}"
|
||||||
|
git push origin "HEAD:${{ steps.cfg.outputs.target_branch }}"
|
||||||
|
fi
|
||||||
15
README.md
15
README.md
@@ -27,6 +27,21 @@ It unifies humans, agents, and infrastructure into a single operating system for
|
|||||||
|
|
||||||
BlackRoad OS is a fully functional web-based operating system interface that brings together AI orchestration, blockchain technology, social media, video streaming, and gaming - all wrapped in a nostalgic Windows 95 aesthetic.
|
BlackRoad OS is a fully functional web-based operating system interface that brings together AI orchestration, blockchain technology, social media, video streaming, and gaming - all wrapped in a nostalgic Windows 95 aesthetic.
|
||||||
|
|
||||||
|
## Monorepo as the Source of Truth
|
||||||
|
|
||||||
|
All BlackRoad services, apps, and docs now live in this monorepo and sync out automatically to their mirror repositories under the `BlackRoad-OS` GitHub organization. Edit here; automation mirrors to the satellites.
|
||||||
|
|
||||||
|
### Canonical layout
|
||||||
|
|
||||||
|
- `services/core-api` → `BlackRoad-OS/blackroad-os-core`
|
||||||
|
- `services/public-api` → `BlackRoad-OS/blackroad-os-api`
|
||||||
|
- `services/operator` → `BlackRoad-OS/blackroad-os-operator`
|
||||||
|
- `apps/prism-console` → `BlackRoad-OS/blackroad-os-prism-console`
|
||||||
|
- `apps/web` → `BlackRoad-OS/blackroad-os-web`
|
||||||
|
- `docs/site` → `BlackRoad-OS/blackroad-os-docs`
|
||||||
|
|
||||||
|
The mapping is machine-readable at `infra/github/sync-config.yml`, and the sync process is documented in `docs/os/monorepo-sync.md`.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### 🤖 AI & Communication
|
### 🤖 AI & Communication
|
||||||
|
|||||||
7
apps/prism-console/README.md
Normal file
7
apps/prism-console/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Prism Console (monorepo-owned)
|
||||||
|
|
||||||
|
- **Canonical path:** `apps/prism-console`
|
||||||
|
- **Mirror:** `BlackRoad-OS/blackroad-os-prism-console`
|
||||||
|
- **Branch:** `main`
|
||||||
|
|
||||||
|
Front-end console code for Prism lives here. Automation syncs changes to the mirror repository.
|
||||||
7
apps/web/README.md
Normal file
7
apps/web/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Web App (monorepo-owned)
|
||||||
|
|
||||||
|
- **Canonical path:** `apps/web`
|
||||||
|
- **Mirror:** `BlackRoad-OS/blackroad-os-web`
|
||||||
|
- **Branch:** `main`
|
||||||
|
|
||||||
|
This is the canonical source for the public web app. Edits here are mirrored automatically.
|
||||||
47
docs/os/monorepo-sync.md
Normal file
47
docs/os/monorepo-sync.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# BlackRoad OS Monorepo Sync
|
||||||
|
|
||||||
|
BlackRoad-Operating-System is the **single source of truth** for every service, app, and docs site under the BlackRoad OS umbrella. All satellite repositories are read-only mirrors. If it cannot be automated from this monorepo, it does not exist.
|
||||||
|
|
||||||
|
## Philosophy
|
||||||
|
- Edit code **only** in this repository.
|
||||||
|
- Each satellite repository maps to exactly one directory in the monorepo (see the mapping table below).
|
||||||
|
- GitHub Actions sync the relevant directory to its target repository after every change—no manual merges.
|
||||||
|
|
||||||
|
## Layout and Ownership
|
||||||
|
- `services/core-api` → `BlackRoad-OS/blackroad-os-core`
|
||||||
|
- `services/public-api` → `BlackRoad-OS/blackroad-os-api`
|
||||||
|
- `services/operator` → `BlackRoad-OS/blackroad-os-operator`
|
||||||
|
- `apps/prism-console` → `BlackRoad-OS/blackroad-os-prism-console`
|
||||||
|
- `apps/web` → `BlackRoad-OS/blackroad-os-web`
|
||||||
|
- `docs/site` → `BlackRoad-OS/blackroad-os-docs`
|
||||||
|
|
||||||
|
The authoritative mapping is codified in `infra/github/sync-config.yml`.
|
||||||
|
|
||||||
|
## How Sync Works
|
||||||
|
1. A push to `main` that touches a mapped path triggers its sync workflow.
|
||||||
|
2. The workflow checks out the monorepo, exports only the mapped directory, and clones the target repository using `${{ secrets.BR_OS_SYNC_TOKEN }}`.
|
||||||
|
3. The target repository is wiped (except `.git`), refreshed with the exported files, committed with the source SHA, and pushed (default is a force-push because the satellite is a mirror).
|
||||||
|
4. A `sync-status.md` file in the satellite captures the source SHA and workflow URL for traceability.
|
||||||
|
5. If there are no changes, the workflow exits cleanly.
|
||||||
|
|
||||||
|
## Onboarding a New Service
|
||||||
|
1. Add an entry to `infra/github/sync-config.yml` with `monorepo_path`, `target_repo`, `target_branch`, and optionally `force_push`.
|
||||||
|
2. Create the corresponding directory (for example `services/new-service/`) and populate it with code.
|
||||||
|
3. Add a new workflow in `.github/workflows/` (copy an existing sync workflow) that sets `SERVICE_KEY` to the new entry and sets the path filter to the new directory.
|
||||||
|
4. (Optional) Add a deploy workflow for the service that builds, tests, and deploys to Railway. Reference `infra/railway/ENVIRONMENT_GUIDE.md` for required env vars.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
- **Non-fast-forward errors:** set `force_push: true` for the service (default) or configure branch protection to allow the automation user to force-push.
|
||||||
|
- **Missing secrets:** ensure `${{ secrets.BR_OS_SYNC_TOKEN }}` is available to sync workflows and `${{ secrets.RAILWAY_TOKEN }}` to deploy workflows.
|
||||||
|
- **Path not syncing:** confirm the workflow `on.push.paths` matches the directory and that the `monorepo_path` in `sync-config.yml` is correct.
|
||||||
|
|
||||||
|
## Repository Guards for Mirrors
|
||||||
|
- Each mirror README should include a “Managed by Monorepo” banner (see `docs/os/satellite-readmes/README.blackroad-os-core.md`).
|
||||||
|
- Recommended branch protection on mirrors:
|
||||||
|
- Require the automation user to be the only actor allowed to force-push to `main`.
|
||||||
|
- Optionally block direct pushes and auto-close PRs with a comment pointing contributors to the monorepo path that owns the code.
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
- `infra/github/sync-config.yml` for the canonical mapping.
|
||||||
|
- `docs/os/satellite-readmes/README.blackroad-os-core.md` for the managed-by-monorepo banner template.
|
||||||
|
- `infra/railway/ENVIRONMENT_GUIDE.md` for deployment expectations.
|
||||||
10
docs/os/satellite-readmes/README.blackroad-os-core.md
Normal file
10
docs/os/satellite-readmes/README.blackroad-os-core.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Managed by Monorepo
|
||||||
|
|
||||||
|
This repository is a read-only mirror of `blackboxprogramming/BlackRoad-Operating-System`.
|
||||||
|
|
||||||
|
- **Source path:** `services/core-api`
|
||||||
|
- **Do NOT edit code directly here.**
|
||||||
|
- All changes must be made in the monorepo and will sync automatically.
|
||||||
|
|
||||||
|
If you opened this file inside the mirror, please submit your changes in the monorepo instead:
|
||||||
|
https://github.com/blackboxprogramming/BlackRoad-Operating-System/tree/main/services/core-api
|
||||||
0
docs/raw/.gitkeep
Normal file
0
docs/raw/.gitkeep
Normal file
0
docs/site/.gitkeep
Normal file
0
docs/site/.gitkeep
Normal file
33
infra/github/sync-config.yml
Normal file
33
infra/github/sync-config.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
services:
|
||||||
|
core-api:
|
||||||
|
monorepo_path: "services/core-api"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-core"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
|
public-api:
|
||||||
|
monorepo_path: "services/public-api"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-api"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
|
operator:
|
||||||
|
monorepo_path: "services/operator"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-operator"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
|
apps:
|
||||||
|
prism-console:
|
||||||
|
monorepo_path: "apps/prism-console"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-prism-console"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
|
web:
|
||||||
|
monorepo_path: "apps/web"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-web"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
|
docs:
|
||||||
|
site:
|
||||||
|
monorepo_path: "docs/site"
|
||||||
|
target_repo: "BlackRoad-OS/blackroad-os-docs"
|
||||||
|
target_branch: "main"
|
||||||
|
force_push: true
|
||||||
39
infra/railway/ENVIRONMENT_GUIDE.md
Normal file
39
infra/railway/ENVIRONMENT_GUIDE.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Railway Environment Guide
|
||||||
|
|
||||||
|
Railway deployments are driven from the monorepo. Each service declares its own variables here so workflows can validate and operators can provision them consistently.
|
||||||
|
|
||||||
|
## Core API (`services/core-api`)
|
||||||
|
- `CORE_API_DATABASE_URL`
|
||||||
|
- `CORE_API_SECRET_KEY`
|
||||||
|
- `CORE_API_ALLOWED_ORIGINS`
|
||||||
|
- `CORE_API_HEALTHCHECK_URL` (defaults to deployed `/health` endpoint)
|
||||||
|
|
||||||
|
## Public API (`services/public-api`)
|
||||||
|
- `PUBLIC_API_DATABASE_URL`
|
||||||
|
- `PUBLIC_API_SECRET_KEY`
|
||||||
|
- `PUBLIC_API_ALLOWED_ORIGINS`
|
||||||
|
- `PUBLIC_API_HEALTHCHECK_URL`
|
||||||
|
|
||||||
|
## Operator (`services/operator`)
|
||||||
|
- `OPERATOR_API_URL`
|
||||||
|
- `OPERATOR_SECRET_KEY`
|
||||||
|
- `OPERATOR_ALLOWED_ORIGINS`
|
||||||
|
- `OPERATOR_HEALTHCHECK_URL`
|
||||||
|
|
||||||
|
## Prism Console (`apps/prism-console`)
|
||||||
|
- `PRISM_API_URL`
|
||||||
|
- `PRISM_CONSOLE_PUBLIC_URL`
|
||||||
|
- `PRISM_CONSOLE_AUTH_TOKEN`
|
||||||
|
|
||||||
|
## Web (`apps/web`)
|
||||||
|
- `WEB_PUBLIC_URL`
|
||||||
|
- `WEB_API_URL`
|
||||||
|
- `WEB_BUILD_ENV`
|
||||||
|
|
||||||
|
## Docs (`docs/site`)
|
||||||
|
- `DOCS_PUBLIC_URL`
|
||||||
|
|
||||||
|
## Deployment Notes
|
||||||
|
- Secrets are injected via `${{ secrets.RAILWAY_TOKEN }}` in GitHub Actions; do not commit credentials.
|
||||||
|
- Healthchecks should respond on `/health` and `/version` for every deployed service.
|
||||||
|
- Update this guide when adding a new service so deployment workflows remain aligned.
|
||||||
7
services/core-api/README.md
Normal file
7
services/core-api/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Core API (monorepo-owned)
|
||||||
|
|
||||||
|
- **Canonical path:** `services/core-api`
|
||||||
|
- **Mirror:** `BlackRoad-OS/blackroad-os-core`
|
||||||
|
- **Branch:** `main`
|
||||||
|
|
||||||
|
This directory contains the core API service for BlackRoad OS. All changes must originate here and will be synced automatically to the mirror repository via `.github/workflows/sync-core-api.yml`.
|
||||||
7
services/operator/README.md
Normal file
7
services/operator/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Operator (monorepo-owned)
|
||||||
|
|
||||||
|
- **Canonical path:** `services/operator`
|
||||||
|
- **Mirror:** `BlackRoad-OS/blackroad-os-operator`
|
||||||
|
- **Branch:** `main`
|
||||||
|
|
||||||
|
This directory is the source of truth for operator automation. Edits sync to the `blackroad-os-operator` mirror repository.
|
||||||
7
services/public-api/README.md
Normal file
7
services/public-api/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Public API (monorepo-owned)
|
||||||
|
|
||||||
|
- **Canonical path:** `services/public-api`
|
||||||
|
- **Mirror:** `BlackRoad-OS/blackroad-os-api`
|
||||||
|
- **Branch:** `main`
|
||||||
|
|
||||||
|
The public-facing API surface for BlackRoad OS lives here. Make changes in this directory; the sync workflow will mirror them to `blackroad-os-api`.
|
||||||
Reference in New Issue
Block a user