Skip to content

Commit 83e0b6e

Browse files
jainejaine
authored andcommitted
chore: initial import
0 parents  commit 83e0b6e

58 files changed

Lines changed: 10584 additions & 0 deletions

Some content is hidden

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

.github/workflows/stage3-smoke.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Stage 3 Smoke
2+
3+
on:
4+
push:
5+
branches: [dev, main]
6+
pull_request:
7+
branches: [dev, main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
smoke:
12+
runs-on: ubuntu-latest
13+
timeout-minutes: 20
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Stage 3 smoke
19+
env:
20+
BLACKCAT_VENDOR_BUILDER: docker
21+
BLACKCAT_SMOKE_BUILD_BUNDLE: "1"
22+
run: |
23+
bash scripts/smoke-stage3.sh
24+

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist/
2+
.phpunit.result.cache
3+
*.log

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# BlackCat Installer
2+
3+
Automated installer that turns a module selection (auth, database, observability, governance, …) into a runnable environment.
4+
It is designed to work both manually (CLI) and as an AI-driven workflow: an agent produces a module list and the installer plans dependency installs, database bootstraps, and docker-compose steps.
5+
6+
## Responsibilities
7+
- Reads the module catalog (`modules.json`; later: `blackcat-modules`).
8+
- Installs dependencies (Composer / npm) for selected modules.
9+
- Generates env overlays / runtime config snippets.
10+
- Runs module bootstrap hooks (e.g. `php bin/auth-http --init`).
11+
- Integrates with CI and AI agents (prompt → module list → plan/apply).
12+
13+
This repository currently contains a skeleton (see `docs/ROADMAP.md`). Next milestones: real Composer/npm dispatch, docker-compose templates, and trust-kernel gated bootstraps.
14+
15+
## Stage 3 (Kernel minimal / FTP)
16+
17+
Stage 3 introduces a “kernel minimal bundle” intended for constrained environments (shared hosting / FTP) where you **cannot** run Composer on the server.
18+
19+
- Template: `templates/kernel-minimal/`
20+
- Build script: `scripts/build-kernel-minimal-bundle.sh`
21+
- Docs: `docs/STAGE3_KERNEL_MINIMAL_BUNDLE.md`
22+
- Hosting preflight (single-file): `tools/blackcat-preflight.php` (upload → run → delete)
23+
- Hosting note: some hostings cannot safely run the web installer (missing TLS verification / outbound HTTPS). In that case, prepare the bundle offline on a trusted device and upload the final artifacts.
24+
- Build note: the Stage 3 build script will build `site/vendor/` using **host Composer** if available, otherwise it falls back to a **Docker-based Composer** build (recommended).
25+
- Local demo (HTTPS): `docker compose -f docker-compose.stage3-demo.yml up --build``https://localhost:8449/_blackcat/setup`
26+
- Live editing: `docker compose -f docker-compose.stage3-demo.yml -f docker-compose.stage3-demo.dev.yml up --build`
27+
28+
## CLI (Stage 1)
29+
30+
```bash
31+
# List available modules
32+
php bin/installer list
33+
34+
# Install selected modules (logs actions and generates `.blackcat/env.generated`)
35+
php bin/installer install --modules=auth-core,observability
36+
37+
# Enable feature views (adds `BC_INCLUDE_FEATURE_VIEWS=1` to the generated env and to bootstrap env)
38+
php bin/installer install --modules=auth-core --include-feature-views
39+
40+
# Change output path or disable env generation
41+
php bin/installer install --modules=auth-core --env-out=config/.env.blackcat
42+
php bin/installer install --modules=observability --no-env
43+
44+
# Disable bootstrap hooks
45+
php bin/installer install --modules=auth-core --no-bootstrap
46+
```
47+
48+
The CLI reads `modules.json` and prints which Composer/npm/docker steps would be needed. It also generates an env file by merging module variables and runs bootstrap commands defined in the catalog (e.g. `php bin/auth-http --init`). Future stages will execute Composer/npm for real and add docker-compose scaffolding.

bin/installer

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env php
2+
<?php
3+
declare(strict_types=1);
4+
5+
require __DIR__ . '/../vendor/autoload.php';
6+
7+
use BlackCat\Installer\Installer;
8+
use Psr\Log\AbstractLogger;
9+
10+
final class CliLogger extends AbstractLogger
11+
{
12+
public function log($level, $message, array $context = []): void
13+
{
14+
echo strtoupper((string) $level) . ' ' . $message . ' ' . json_encode($context) . PHP_EOL;
15+
}
16+
}
17+
18+
$installer = new Installer(null, new CliLogger());
19+
20+
$argv = $_SERVER['argv'] ?? [];
21+
$command = $argv[1] ?? 'help';
22+
$args = array_slice($argv, 2);
23+
24+
switch ($command) {
25+
case 'list':
26+
echo json_encode($installer->available(), JSON_PRETTY_PRINT) . PHP_EOL;
27+
break;
28+
case 'install':
29+
[$mods, $envOut, $runBootstrap, $includeFeatureViews] = parseInstallArgs($args);
30+
if ($mods === []) {
31+
fwrite(STDERR, "Usage: installer install --modules=auth-core,observability\n");
32+
exit(1);
33+
}
34+
$extraEnv = $includeFeatureViews ? ['BC_INCLUDE_FEATURE_VIEWS' => '1'] : [];
35+
if ($includeFeatureViews) {
36+
$_ENV['BC_INCLUDE_FEATURE_VIEWS'] = '1';
37+
if (function_exists('putenv')) {
38+
putenv('BC_INCLUDE_FEATURE_VIEWS=1');
39+
} else {
40+
fwrite(STDERR, "Warning: putenv() is disabled; bootstrap commands may not see BC_INCLUDE_FEATURE_VIEWS.\n");
41+
}
42+
}
43+
$installer->install($mods, $envOut, $runBootstrap, $extraEnv);
44+
break;
45+
case 'help':
46+
default:
47+
echo <<<TXT
48+
BlackCat Installer CLI
49+
50+
Usage:
51+
installer list
52+
installer install --modules=auth-core,observability
53+
TXT;
54+
exit($command === 'help' ? 0 : 1);
55+
}
56+
57+
function parseInstallArgs(array $args): array
58+
{
59+
$modules = [];
60+
$envOut = '.blackcat/env.generated';
61+
$runBootstrap = true;
62+
$includeFeatureViews = false;
63+
foreach ($args as $index => $arg) {
64+
if (str_starts_with($arg, '--modules=')) {
65+
$modules = explode(',', substr($arg, 10));
66+
} elseif ($arg === '--modules' && isset($args[$index + 1])) {
67+
$modules = explode(',', $args[$index + 1]);
68+
} elseif (str_starts_with($arg, '--env-out=')) {
69+
$envOut = substr($arg, 10);
70+
} elseif ($arg === '--env-out' && isset($args[$index + 1])) {
71+
$envOut = $args[$index + 1];
72+
} elseif ($arg === '--no-env') {
73+
$envOut = null;
74+
} elseif ($arg === '--no-bootstrap') {
75+
$runBootstrap = false;
76+
} elseif ($arg === '--include-feature-views') {
77+
$includeFeatureViews = true;
78+
}
79+
}
80+
$modules = array_values(array_filter(array_map('trim', $modules)));
81+
return [$modules, $envOut, $runBootstrap, $includeFeatureViews];
82+
}

docker-compose.stage3-demo.dev.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
stage3-demo:
3+
volumes:
4+
# Live-edit the setup UI without rebuilding the image.
5+
- ./templates/kernel-minimal/site/_blackcat/setup.php:/srv/bundle/site/_blackcat/setup.php:ro
6+
- ./templates/kernel-minimal/site/_blackcat/error-ui.php:/srv/bundle/site/_blackcat/error-ui.php:ro
7+
- ./templates/kernel-minimal/site/_blackcat/asset:/srv/bundle/site/_blackcat/asset:ro
8+
- ./templates/kernel-minimal/site/public/index.php:/srv/bundle/site/public/index.php:ro
9+
- ./templates/kernel-minimal/site/public/.htaccess:/srv/bundle/site/public/.htaccess:ro
10+
- ./templates/kernel-minimal/site/public/_blackcat:/srv/bundle/site/public/_blackcat:ro

docker-compose.stage3-demo.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
services:
2+
stage3-demo:
3+
build:
4+
context: ..
5+
dockerfile: blackcat-installer/docker/stage3-demo/Dockerfile
6+
ports:
7+
- "8099:80"
8+
- "8449:443"
9+
restart: unless-stopped
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<VirtualHost *:80>
2+
ServerName localhost
3+
4+
DocumentRoot /srv/bundle/site/public
5+
<Directory /srv/bundle/site/public>
6+
AllowOverride All
7+
Require all granted
8+
# Demo hardening (so strict preflight can pass by default):
9+
# - Disables information disclosure via display_errors
10+
# - Limits filesystem access via open_basedir
11+
# - Disables process execution primitives
12+
php_admin_flag display_errors Off
13+
php_admin_flag display_startup_errors Off
14+
php_admin_flag log_errors On
15+
php_admin_flag enable_dl Off
16+
php_admin_value open_basedir "/srv/bundle:/tmp:/etc/ssl/certs:/etc/ssl"
17+
php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open,pcntl_exec"
18+
</Directory>
19+
20+
ErrorLog ${APACHE_LOG_DIR}/error.log
21+
CustomLog ${APACHE_LOG_DIR}/access.log combined
22+
</VirtualHost>

docker/stage3-demo/Dockerfile

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
FROM php:8.3-cli AS vendor
2+
3+
WORKDIR /build
4+
5+
RUN apt-get update \
6+
&& apt-get install -y --no-install-recommends git unzip ca-certificates \
7+
&& rm -rf /var/lib/apt/lists/*
8+
9+
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
10+
11+
COPY blackcat-core /workspace/blackcat-core
12+
COPY blackcat-config /workspace/blackcat-config
13+
14+
RUN mkdir -p /build/app
15+
WORKDIR /build/app
16+
17+
RUN cat > composer.json <<'JSON'
18+
{
19+
"name": "blackcatacademy/blackcat-stage3-demo-build",
20+
"type": "project",
21+
"license": "proprietary",
22+
"require": {
23+
"blackcatacademy/blackcat-core": "dev-main",
24+
"blackcatacademy/blackcat-config": "dev-main"
25+
},
26+
"repositories": [
27+
{ "type": "path", "url": "/workspace/blackcat-core", "options": { "symlink": false } },
28+
{ "type": "path", "url": "/workspace/blackcat-config", "options": { "symlink": false } }
29+
],
30+
"config": {
31+
"optimize-autoloader": true,
32+
"sort-packages": true
33+
},
34+
"minimum-stability": "dev",
35+
"prefer-stable": true
36+
}
37+
JSON
38+
39+
RUN composer install --no-dev --optimize-autoloader --classmap-authoritative --no-interaction
40+
41+
FROM php:8.3-apache
42+
43+
RUN a2enmod rewrite ssl headers
44+
RUN a2ensite default-ssl
45+
46+
COPY blackcat-installer/docker/stage3-demo/000-default.conf /etc/apache2/sites-available/000-default.conf
47+
COPY blackcat-installer/docker/stage3-demo/default-ssl.conf /etc/apache2/sites-available/default-ssl.conf
48+
49+
# Demo hardening (applies to Apache SAPI; keeps Stage 3 strict preflight green by default).
50+
# Note: `disable_functions` cannot be reliably set per-vhost, so we set it here at the PHP_INI_SYSTEM level.
51+
RUN { \
52+
echo "display_errors=0"; \
53+
echo "display_startup_errors=0"; \
54+
echo "log_errors=1"; \
55+
echo "enable_dl=0"; \
56+
echo "open_basedir=/srv/bundle:/tmp:/etc/ssl/certs:/etc/ssl"; \
57+
echo "disable_functions=exec,shell_exec,system,passthru,popen,proc_open,pcntl_exec"; \
58+
} > /usr/local/etc/php/conf.d/blackcat-demo-hardening.ini
59+
60+
RUN mkdir -p /etc/ssl/private \
61+
&& openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
62+
-subj "/CN=localhost" \
63+
-keyout /etc/ssl/private/blackcat-demo.key \
64+
-out /etc/ssl/certs/blackcat-demo.crt
65+
66+
WORKDIR /srv/bundle
67+
68+
COPY blackcat-installer/templates/kernel-minimal/site /srv/bundle/site
69+
COPY --from=vendor /build/app/vendor /srv/bundle/site/vendor
70+
71+
# Filesystem hardening:
72+
# - integrity root (site/) is read-only
73+
# - mutable state (.blackcat/) is writable by www-data
74+
# - config.runtime.json is written at bundle root (writable by www-data via group)
75+
RUN mkdir -p /srv/bundle/.blackcat \
76+
&& chown -R root:root /srv/bundle/site \
77+
&& chmod -R a-w /srv/bundle/site \
78+
&& chown -R www-data:www-data /srv/bundle/.blackcat \
79+
&& chmod 0700 /srv/bundle/.blackcat \
80+
&& chown root:www-data /srv/bundle \
81+
&& chmod 0770 /srv/bundle
82+
83+
EXPOSE 80 443
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<IfModule mod_ssl.c>
2+
<VirtualHost *:443>
3+
ServerName localhost
4+
5+
DocumentRoot /srv/bundle/site/public
6+
<Directory /srv/bundle/site/public>
7+
AllowOverride All
8+
Require all granted
9+
# Demo hardening (so strict preflight can pass by default):
10+
# - Disables information disclosure via display_errors
11+
# - Limits filesystem access via open_basedir
12+
# - Disables process execution primitives
13+
php_admin_flag display_errors Off
14+
php_admin_flag display_startup_errors Off
15+
php_admin_flag log_errors On
16+
php_admin_flag enable_dl Off
17+
php_admin_value open_basedir "/srv/bundle:/tmp:/etc/ssl/certs:/etc/ssl"
18+
php_admin_value disable_functions "exec,shell_exec,system,passthru,popen,proc_open,pcntl_exec"
19+
</Directory>
20+
21+
ErrorLog ${APACHE_LOG_DIR}/error-ssl.log
22+
CustomLog ${APACHE_LOG_DIR}/access-ssl.log combined
23+
24+
SSLEngine on
25+
SSLCertificateFile /etc/ssl/certs/blackcat-demo.crt
26+
SSLCertificateKeyFile /etc/ssl/private/blackcat-demo.key
27+
28+
# Demo hardening (no caching of installer responses)
29+
Header always set X-Content-Type-Options "nosniff"
30+
Header always set X-Frame-Options "DENY"
31+
Header always set Referrer-Policy "no-referrer"
32+
</VirtualHost>
33+
</IfModule>

docs/ROADMAP.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# BlackCat Installer — Roadmap
2+
3+
## Stage 1 — Skeleton ✅
4+
- CLI `blackcat-installer list/install` reads `modules.json`.
5+
- Dry-run logging only (prepares for composer/npm dispatch).
6+
7+
## Stage 2 — Bootstrap workflows (in progress)
8+
- ✅ Generate `.env` overlays from module variables (`--env-out`, `--no-env`).
9+
- ✅ Bootstrap runner (executes `bootstrap` commands; optional `--no-bootstrap`).
10+
- ▢ Templates for docker-compose stacks (monitoring, database).
11+
12+
## Stage 3 — Trust Kernel bootstrap (planned)
13+
- Verify official releases before any privileged action:
14+
- verify signed integrity manifests (checksums + signatures),
15+
- verify the Web3 anchor (ReleaseRegistry + per-install InstanceController).
16+
- Provide a “minimal install” mode:
17+
- ✅ kernel-minimal bundle template (`templates/kernel-minimal/`)
18+
- ✅ token-gated one-time setup UI (`/_blackcat/setup`)
19+
- ✅ build helper script (`scripts/build-kernel-minimal-bundle.sh`)
20+
- target server installs only `blackcat-core` (+ deps) and a file-based runtime config
21+
- no CLI requirement on the target (works even in constrained environments)
22+
- Multi-device approval ceremony (N-of-M signers) to:
23+
- clone/create the per-install controller contract,
24+
- pin the chosen trust mode (`root+uri` vs `full`) and policy,
25+
- register emergency + upgrade authorities.
26+
- Enforce secure bootstrap:
27+
- refuse to create/accept admin credentials without HTTPS (best available mechanism),
28+
- in strict mode, record a bootstrap event hash on-chain (tamper-evident audit trail).
29+
30+
## Stage 4 — AI Integration
31+
- REST API + OpenAI agent workflow (prompt → modules): `installer ai-setup "project needs auth + analytics"`.
32+
33+
## Stage 5 — Frontend org support
34+
- Auto-clone FE repos, install UI modules, link them with backend modules.
35+
36+
## Stage 6 — Cloud deploy
37+
- Provisioning Terraform/helm templates, multi-env pipeline.

0 commit comments

Comments
 (0)