docs: add examples for Go, PHP, and VM commands

This commit is contained in:
Snider 2026-01-29 21:33:10 +00:00
parent 55d4f0f385
commit c1920e541e
120 changed files with 10254 additions and 5052 deletions

View file

@ -5,11 +5,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Commands
```bash
composer test # Run all tests
composer test -- --filter=Name # Run single test by name
composer pint # Format code with Laravel Pint
composer test # Run all tests (PHPUnit)
composer test -- --filter=Name # Run single test by name
composer test -- --testsuite=Unit # Run specific test suite
composer pint # Format code with Laravel Pint
./vendor/bin/pint --dirty # Format only changed files
```
## Coding Standards
- **UK English**: colour, organisation, centre (never American spellings)
- **Strict types**: `declare(strict_types=1);` in every PHP file
- **Type hints**: All parameters and return types required
- **Testing**: PHPUnit with Orchestra Testbench
- **License**: EUPL-1.2
## Architecture
### Event-Driven Module Loading
@ -22,6 +32,8 @@ LifecycleEventProvider::register()
└── ModuleRegistry::register() # Wires LazyModuleListener for each event
```
**Key benefit**: Web requests don't load admin modules; API requests don't load web modules.
### Frontages
Frontages are ServiceProviders in `src/Core/Front/` that fire context-specific lifecycle events:
@ -34,19 +46,22 @@ Frontages are ServiceProviders in `src/Core/Front/` that fire context-specific l
| Client | `ClientRoutesRegistering` | `client` | Authenticated SaaS |
| Cli | `ConsoleBooting` | - | Artisan commands |
| Mcp | `McpToolsRegistering` | - | MCP tool handlers |
| - | `FrameworkBooted` | - | Late-stage initialisation |
### L1 Packages
Subdirectories under `src/Core/` are self-contained "L1 packages" with their own Boot.php, migrations, tests, and views:
```
src/Core/Activity/ # Activity logging
src/Core/Activity/ # Activity logging (wraps spatie/laravel-activitylog)
src/Core/Bouncer/ # Security blocking/redirects
src/Core/Cdn/ # CDN integration
src/Core/Config/ # Dynamic configuration
src/Core/Front/ # Frontage system (Web, Admin, Api, Client, Cli, Mcp)
src/Core/Lang/ # Translation system
src/Core/Media/ # Media handling
src/Core/Media/ # Media handling with thumbnail helpers
src/Core/Search/ # Search functionality
src/Core/Seo/ # SEO utilities
```
### Module Pattern
@ -63,6 +78,7 @@ class Boot
{
$event->views('example', __DIR__.'/Views');
$event->routes(fn () => require __DIR__.'/Routes/web.php');
$event->livewire('example.widget', ExampleWidget::class);
}
}
```
@ -88,20 +104,62 @@ class CreateOrder
{
use Action;
public function __construct(private OrderService $orders) {}
public function handle(User $user, array $data): Order
{
return Order::create($data);
return $this->orders->create($user, $data);
}
}
// Usage: CreateOrder::run($user, $validated);
```
### Seeder Ordering
Seeders use PHP attributes for dependency ordering:
```php
use Core\Database\Seeders\Attributes\SeederPriority;
use Core\Database\Seeders\Attributes\SeederAfter;
#[SeederPriority(50)] // Lower runs first (default 50)
#[SeederAfter(FeatureSeeder::class)]
class PackageSeeder extends Seeder
{
public function run(): void
{
if (! Schema::hasTable('packages')) return; // Guard missing tables
// ...
}
}
```
### HLCRF Layout System
Data-driven layouts with five regions (Header, Left, Content, Right, Footer):
```php
use Core\Front\Components\Layout;
$page = Layout::make('HCF') // Variant: Header-Content-Footer
->h(view('header'))
->c($content)
->f(view('footer'));
```
Variant strings: `C` (content only), `HCF` (standard page), `HLCF` (with sidebar), `HLCRF` (full dashboard).
## Testing
Uses Orchestra Testbench. Tests can live:
Uses Orchestra Testbench with in-memory SQLite. Tests can live:
- `tests/Feature/` and `tests/Unit/` - main test suites
- `src/Core/{Package}/Tests/` - L1 package co-located tests
- `src/Mod/{Module}/Tests/` - module co-located tests
Test fixtures are in `tests/Fixtures/`.
Base test class provides:
```php
$this->getFixturePath('Mod') // Returns tests/Fixtures/Mod path
```

View file

@ -0,0 +1,402 @@
---
title: Architecture
description: Technical architecture of the core-commerce package
updated: 2026-01-29
---
# Commerce Architecture
This document describes the technical architecture of the `core-commerce` package, which provides billing, subscriptions, and payment processing for the Host UK platform.
## Overview
The commerce module implements a multi-gateway payment system supporting cryptocurrency (BTCPay) and traditional card payments (Stripe). It handles the complete commerce lifecycle from checkout to recurring billing, dunning, and refunds.
```
┌─────────────────────────────────────────────────────────────────┐
│ Commerce Module │
├─────────────────────────────────────────────────────────────────┤
│ Services Layer │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Commerce │ │ Subscription │ │ Dunning │ │
│ │ Service │ │ Service │ │ Service │ │
│ └─────────────┘ └──────────────┘ └───────────────┘ │
│ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Invoice │ │ Coupon │ │ Tax │ │
│ │ Service │ │ Service │ │ Service │ │
│ └─────────────┘ └──────────────┘ └───────────────┘ │
├─────────────────────────────────────────────────────────────────┤
│ Gateway Layer │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ BTCPayGateway │ │ StripeGateway │ │
│ │ (Primary) │ │ (Secondary) │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │ │ │
│ └────────────┬─────────────┘ │
│ │ │
│ ┌────────────▼─────────────┐ │
│ │ PaymentGatewayContract │ │
│ └──────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
## Core Concepts
### Orderable Interface
The commerce system uses polymorphic relationships via the `Orderable` contract. Both `Workspace` and `User` models can place orders, enabling:
- **Workspace orders**: Subscription packages, team features
- **User orders**: Individual boosts, one-time purchases
```php
interface Orderable
{
public function getBillingName(): string;
public function getBillingEmail(): string;
public function getBillingAddress(): array;
public function getTaxCountry(): ?string;
}
```
### Order Lifecycle
```
┌──────────┐ ┌────────────┐ ┌──────────┐ ┌────────┐
│ pending │───▶│ processing │───▶│ paid │───▶│refunded│
└──────────┘ └────────────┘ └──────────┘ └────────┘
│ │
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│cancelled │ │ failed │
└──────────┘ └──────────┘
```
1. **pending**: Order created, awaiting checkout
2. **processing**: Customer redirected to payment gateway
3. **paid**: Payment confirmed, entitlements provisioned
4. **failed**: Payment declined or expired
5. **cancelled**: Customer abandoned checkout
6. **refunded**: Full refund processed
### Subscription States
```
┌────────┐ ┌──────────┐ ┌────────┐ ┌───────────┐
│ active │───▶│ past_due │───▶│ paused │───▶│ cancelled │
└────────┘ └──────────┘ └────────┘ └───────────┘
│ │ │
▼ │ │
┌──────────┐ │ │
│ trialing │────────┘ │
└──────────┘ │
│ │
└─────────────────────────────┘
```
- **active**: Subscription in good standing
- **trialing**: Within trial period (no payment required)
- **past_due**: Payment failed, within retry window
- **paused**: Billing paused (dunning or user-initiated)
- **cancelled**: Subscription ended
## Service Layer
### CommerceService
Main orchestration service. Coordinates order creation, checkout, and fulfillment.
```php
// Create an order
$order = $commerce->createOrder($workspace, $package, 'monthly', $coupon);
// Create checkout session (redirects to gateway)
$checkout = $commerce->createCheckout($order, 'btcpay', $successUrl, $cancelUrl);
// Fulfill order after payment (called by webhook)
$commerce->fulfillOrder($order, $payment);
```
Key responsibilities:
- Gateway selection and initialization
- Customer management across gateways
- Order-to-entitlement provisioning
- Currency formatting and conversion
### SubscriptionService
Manages subscription lifecycle without gateway interaction.
```php
// Create local subscription record
$subscription = $subscriptions->create($workspacePackage, 'monthly');
// Handle plan changes with proration
$result = $subscriptions->changePlan($subscription, $newPackage, prorate: true);
// Pause/unpause with limits
$subscriptions->pause($subscription);
$subscriptions->unpause($subscription);
```
Proration calculation:
```
creditAmount = currentPrice * (daysRemaining / totalPeriodDays)
proratedNewCost = newPrice * (daysRemaining / totalPeriodDays)
netAmount = proratedNewCost - creditAmount
```
### DunningService
Handles failed payment recovery with exponential backoff.
```
Day 0: Payment fails → subscription marked past_due
Day 1: First retry
Day 3: Second retry
Day 7: Third retry → subscription paused
Day 14: Workspace suspended (features restricted)
Day 30: Subscription cancelled
```
Configuration in `config.php`:
```php
'dunning' => [
'retry_days' => [1, 3, 7],
'suspend_after_days' => 14,
'cancel_after_days' => 30,
'initial_grace_hours' => 24,
],
```
### TaxService
Jurisdiction-based tax calculation supporting:
- UK VAT (20%)
- EU VAT via VIES validation
- US state sales tax (nexus-based)
- Australian GST (10%)
B2B reverse charge is applied automatically when a valid VAT number is provided for EU customers.
```php
$taxResult = $taxService->calculate($workspace, $amount);
// Returns: TaxResult with taxAmount, taxRate, jurisdiction, isExempt
```
## Payment Gateways
### PaymentGatewayContract
All gateways implement this interface ensuring consistent behavior:
```php
interface PaymentGatewayContract
{
// Identity
public function getIdentifier(): string;
public function isEnabled(): bool;
// Customer management
public function createCustomer(Workspace $workspace): string;
// Checkout
public function createCheckoutSession(Order $order, ...): array;
public function getCheckoutSession(string $sessionId): array;
// Payments
public function charge(Workspace $workspace, int $amountCents, ...): Payment;
public function chargePaymentMethod(PaymentMethod $pm, ...): Payment;
// Subscriptions
public function createSubscription(Workspace $workspace, ...): Subscription;
public function cancelSubscription(Subscription $sub, bool $immediately): void;
// Webhooks
public function verifyWebhookSignature(string $payload, string $sig): bool;
public function parseWebhookEvent(string $payload): array;
}
```
### BTCPayGateway (Primary)
Cryptocurrency payment gateway supporting BTC, LTC, XMR.
**Characteristics:**
- No saved payment methods (each payment is unique)
- No automatic recurring billing (requires customer action)
- Invoice-based workflow with expiry
- HMAC signature verification for webhooks
**Webhook Events:**
- `InvoiceCreated` → No action
- `InvoiceReceivedPayment` → Order status: processing
- `InvoiceProcessing` → Waiting for confirmations
- `InvoiceSettled` → Fulfill order
- `InvoiceExpired` → Mark order failed
### StripeGateway (Secondary)
Traditional card payment gateway.
**Characteristics:**
- Saved payment methods for recurring
- Automatic subscription billing
- Setup intents for card-on-file
- Stripe Customer Portal integration
**Webhook Events:**
- `checkout.session.completed` → Fulfill order
- `invoice.paid` → Renew subscription
- `invoice.payment_failed` → Trigger dunning
- `customer.subscription.deleted` → Revoke entitlements
## Data Models
### Entity Relationship
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Workspace │────▶│ Order │────▶│ OrderItem │
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ ▼
│ ┌─────────────┐ ┌─────────────┐
│ │ Invoice │────▶│InvoiceItem │
│ └─────────────┘ └─────────────┘
│ │
│ ▼
│ ┌─────────────┐ ┌─────────────┐
└───────────▶│ Payment │────▶│ Refund │
└─────────────┘ └─────────────┘
┌─────────────┐ ┌─────────────┐
│ Coupon │────▶│ CouponUsage │
└─────────────┘ └─────────────┘
```
### Multi-Entity Commerce (M1/M2/M3)
The commerce module supports a hierarchical entity structure:
- **M1 (Master Company)**: Source of truth, owns product catalog
- **M2 (Facade/Storefront)**: Selects from M1 catalog, can override content
- **M3 (Dropshipper)**: Full inheritance, no management responsibility
```
┌─────────┐
│ M1 │ ← Product catalog owner
└────┬────┘
┌────────┴────────┐
│ │
┌─────▼─────┐ ┌─────▼─────┐
│ M2 │ │ M2 │ ← Storefronts
└─────┬─────┘ └───────────┘
┌─────▼─────┐
│ M3 │ ← Dropshipper
└───────────┘
```
Permission matrix controls which operations each entity type can perform, with a "training mode" for undefined permissions.
## Event System
### Domain Events
```php
// Dispatched automatically on model changes
SubscriptionCreated::class → RewardAgentReferralOnSubscription
SubscriptionRenewed::class → ResetUsageOnRenewal
OrderPaid::class → CreateReferralCommission
```
### Listeners
- `ProvisionSocialHostSubscription`: Product-specific provisioning logic
- `RewardAgentReferralOnSubscription`: Attribute referral for new subscriptions
- `ResetUsageOnRenewal`: Clear usage counters on billing period reset
- `CreateReferralCommission`: Calculate affiliate commission on paid orders
## Directory Structure
```
core-commerce/
├── Boot.php # ServiceProvider, event registration
├── config.php # All configuration (currencies, gateways, tax)
├── Concerns/ # Traits for models
├── Console/ # Artisan commands (dunning, reminders)
├── Contracts/ # Interfaces (Orderable)
├── Controllers/ # HTTP controllers
│ ├── Api/ # REST API endpoints
│ └── Webhooks/ # Gateway webhook handlers
├── Data/ # DTOs and value objects
├── Events/ # Domain events
├── Exceptions/ # Custom exceptions
├── Jobs/ # Queue jobs
├── Lang/ # Translations
├── Listeners/ # Event listeners
├── Mail/ # Mailable classes
├── Mcp/ # MCP tool handlers
├── Middleware/ # HTTP middleware
├── Migrations/ # Database migrations
├── Models/ # Eloquent models
├── Notifications/ # Laravel notifications
├── routes/ # Route definitions
├── Services/ # Business logic layer
│ └── PaymentGateway/ # Gateway implementations
├── tests/ # Pest tests
└── View/ # Blade templates and Livewire components
├── Blade/ # Blade templates
└── Modal/ # Livewire components (Admin/Web)
```
## Configuration
All commerce configuration lives in `config.php`:
```php
return [
'currency' => 'GBP', // Default currency
'currencies' => [...], // Supported currencies, exchange rates
'gateways' => [
'btcpay' => [...], // Primary gateway
'stripe' => [...], // Secondary gateway
],
'billing' => [...], // Invoice prefixes, due days
'dunning' => [...], // Retry schedule, suspension timing
'tax' => [...], // Tax rates, VAT validation
'subscriptions' => [...], // Proration, pause limits
'checkout' => [...], // Session TTL, country restrictions
'features' => [...], // Toggle coupons, refunds, trials
'usage_billing' => [...], // Metered billing settings
'matrix' => [...], // M1/M2/M3 permission matrix
];
```
## Testing
Tests use Pest with `RefreshDatabase` trait:
```bash
# Run all tests
composer test
# Run specific test file
vendor/bin/pest tests/Feature/CheckoutFlowTest.php
# Run tests matching pattern
vendor/bin/pest --filter="proration"
```
Test categories:
- `CheckoutFlowTest`: End-to-end order flow
- `SubscriptionServiceTest`: Subscription lifecycle, proration
- `DunningServiceTest`: Payment recovery flows
- `WebhookTest`: Gateway webhook handling
- `TaxServiceTest`: Tax calculation, VAT validation
- `CouponServiceTest`: Discount application
- `RefundServiceTest`: Refund processing

View file

@ -0,0 +1,327 @@
---
title: Security
description: Security considerations and audit notes for core-commerce
updated: 2026-01-29
---
# Security Considerations
This document outlines security controls, known risks, and recommendations for the `core-commerce` package.
## Authentication & Authorisation
### API Authentication
| Endpoint Type | Authentication Method | Notes |
|--------------|----------------------|-------|
| Webhooks (`/api/webhooks/*`) | HMAC signature | Gateway-specific verification |
| Billing API (`/api/commerce/*`) | Laravel `auth` middleware | Session/Sanctum token |
| Provisioning API | Bearer token (planned) | Currently commented out |
### Webhook Security
Both payment gateways use HMAC signature verification:
**BTCPay:**
```php
// Signature in BTCPay-Sig header
$expectedSignature = hash_hmac('sha256', $payload, $webhookSecret);
hash_equals($expectedSignature, $providedSignature);
```
**Stripe:**
```php
// Uses Stripe SDK signature verification
\Stripe\Webhook::constructEvent($payload, $signature, $webhookSecret);
```
### Current Gaps
1. **No idempotency enforcement** - Webhook handlers check order state (`isPaid()`) but don't store processed event IDs. Replay attacks within the state-check window are possible.
2. **No IP allowlisting** - Webhook endpoints accept connections from any IP. Consider adding gateway IP ranges to allowlist.
3. **Rate limiting is global** - Current throttle (`120,1`) applies globally, not per-IP. A malicious actor could exhaust the limit.
## Data Protection
### Sensitive Data Handling
| Data Type | Storage | Protection |
|-----------|---------|------------|
| Card details | Never stored | Handled by gateways via redirect |
| Gateway API keys | Environment variables | Not in codebase |
| Webhook secrets | Environment variables | Used for HMAC |
| Tax IDs (VAT numbers) | Encrypted column recommended | Currently plain text |
| Billing addresses | Database JSON column | Consider encryption |
### PCI DSS Compliance
The commerce module is designed to be **PCI DSS SAQ A** compliant:
- No card data ever touches Host UK servers
- Checkout redirects to hosted payment pages (BTCPay/Stripe)
- Only tokenized references (customer IDs, payment method IDs) are stored
- No direct card number input in application
### GDPR Considerations
Personal data in commerce models:
- `orders.billing_name`, `billing_email`, `billing_address`
- `invoices.billing_*` fields
- `referrals.ip_address`, `user_agent`
**Recommendations:**
- Implement data export for billing history (right of access)
- Add retention policy for old orders/invoices
- Hash or truncate IP addresses after 90 days
- Document lawful basis for processing (contract performance)
## Input Validation
### Current Controls
```php
// Coupon codes normalized
$data['code'] = strtoupper($data['code']);
// Order totals calculated server-side
$taxResult = $this->taxService->calculateForOrderable($orderable, $taxableAmount);
$total = $subtotal - $discountAmount + $setupFee + $taxResult->taxAmount;
// Gateway responses logged without sensitive data
protected function sanitiseErrorMessage($response): string
```
### Validation Gaps
1. **Billing address structure** - Accepted as array without schema validation
2. **Coupon code length** - No maximum length enforcement
3. **Metadata fields** - JSON columns accept arbitrary structure
### Recommendations
```php
// Add validation rules
$rules = [
'billing_address.line1' => ['required', 'string', 'max:255'],
'billing_address.city' => ['required', 'string', 'max:100'],
'billing_address.country' => ['required', 'string', 'size:2'],
'billing_address.postal_code' => ['required', 'string', 'max:20'],
'coupon_code' => ['nullable', 'string', 'max:32', 'alpha_dash'],
];
```
## Transaction Security
### Idempotency
Order creation supports idempotency keys:
```php
if ($idempotencyKey) {
$existingOrder = Order::where('idempotency_key', $idempotencyKey)->first();
if ($existingOrder) {
return $existingOrder;
}
}
```
**Gap:** Webhooks don't use idempotency. Add `WebhookEvent` lookup:
```php
if (WebhookEvent::where('idempotency_key', $event['id'])->exists()) {
return response('Already processed', 200);
}
```
### Race Conditions
**Identified risks:**
1. **Concurrent subscription operations** - Pause/unpause/cancel without locks
2. **Coupon redemption** - `incrementUsage()` without atomic check
3. **Payout requests** - Commission assignment without row locks
**Mitigation:** Add `FOR UPDATE` locks or use atomic operations:
```php
// Use DB::transaction with locking
$commission = ReferralCommission::lockForUpdate()
->where('id', $commissionId)
->where('status', 'matured')
->first();
```
### Amount Verification
**Current state:** BTCPay webhook trusts order total without verifying against gateway response.
**Risk:** Under/overpayment handling undefined.
**Recommendation:**
```php
$settledAmount = $invoiceData['raw']['amount'] ?? null;
if ($settledAmount !== null && abs($settledAmount - $order->total) > 0.01) {
Log::warning('Payment amount mismatch', [
'order_total' => $order->total,
'settled_amount' => $settledAmount,
]);
// Handle partial payment or overpayment
}
```
## Fraud Prevention
### Current Controls
- Checkout session TTL (30 minutes default)
- Rate limiting on API endpoints
- Idempotency keys for order creation
### Missing Controls
1. **Velocity checks** - No detection of rapid-fire order attempts
2. **Geo-blocking** - No IP geolocation validation against billing country
3. **Card testing detection** - No small-amount charge pattern detection
4. **Device fingerprinting** - No device/browser tracking
### Recommendations
```php
// Add CheckoutRateLimiter to createCheckout
$rateLimiter = app(CheckoutRateLimiter::class);
if (!$rateLimiter->attempt($workspace->id)) {
throw new TooManyCheckoutAttemptsException();
}
// Consider Stripe Radar for card payments
'stripe' => [
'radar_enabled' => true,
'block_threshold' => 75, // Block if risk score > 75
],
```
## Audit Logging
### What's Logged
- Order status changes via `LogsActivity` trait
- Subscription status changes via `LogsActivity` trait
- Webhook events via `WebhookLogger` service
- Payment failures and retries
### What's Not Logged
- Failed authentication attempts on billing API
- Coupon validation failures
- Tax ID validation API calls
- Admin actions on refunds/credit notes
### Recommendations
Add audit events for:
```php
// Sensitive operations
activity('commerce')
->causedBy($admin)
->performedOn($refund)
->withProperties(['reason' => $reason])
->log('Refund processed');
```
## Secrets Management
### Environment Variables
```bash
# Gateway credentials
BTCPAY_URL=https://pay.host.uk.com
BTCPAY_STORE_ID=xxx
BTCPAY_API_KEY=xxx
BTCPAY_WEBHOOK_SECRET=xxx
STRIPE_KEY=pk_xxx
STRIPE_SECRET=sk_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx
# Tax API credentials
COMMERCE_EXCHANGE_RATE_API_KEY=xxx
```
### Key Rotation
No automated key rotation currently implemented.
**Recommendations:**
- Store credentials in secrets manager (AWS Secrets Manager, HashiCorp Vault)
- Implement webhook secret rotation with grace period
- Alert on API key exposure in logs
## Security Checklist
### Before Production
- [ ] Webhook secrets are unique per environment
- [ ] Rate limiting tuned for expected traffic
- [ ] Error messages don't leak internal details
- [ ] API keys not in version control
- [ ] SSL/TLS required for all endpoints
### Ongoing
- [ ] Monitor webhook failure rates
- [ ] Review failed payment patterns weekly
- [ ] Audit refund activity monthly
- [ ] Update gateway SDKs quarterly
- [ ] Penetration test annually
## Incident Response
### Compromised API Key
1. Revoke key immediately in gateway dashboard
2. Generate new key
3. Update environment variable
4. Restart application
5. Audit recent transactions for anomalies
### Webhook Secret Leaked
1. Generate new secret in gateway
2. Update both old and new in config (grace period)
3. Monitor for invalid signature attempts
4. Remove old secret after 24 hours
### Suspected Fraud
1. Pause affected subscription
2. Flag orders for manual review
3. Contact gateway for chargeback advice
4. Document in incident log
## Third-Party Dependencies
### Gateway SDKs
| Package | Version | Security Notes |
|---------|---------|----------------|
| `stripe/stripe-php` | ^12.0 | Keep updated for security patches |
### Other Dependencies
- `spatie/laravel-activitylog` - Audit logging
- `barryvdh/laravel-dompdf` - PDF generation (ensure no user input in HTML)
### Dependency Audit
Run regularly:
```bash
composer audit
```
## Contact
Report security issues to: security@host.uk.com
Do not open public issues for security vulnerabilities.

View file

@ -0,0 +1,387 @@
---
title: Webhooks
description: Payment gateway webhook handling documentation
updated: 2026-01-29
---
# Webhook Handling
This document describes how payment gateway webhooks are processed in the commerce module.
## Overview
Payment gateways notify the application of payment events via webhooks. These are HTTP POST requests sent to predefined endpoints when payment state changes.
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ BTCPay │ │ Host UK │ │ Stripe │
│ Server │ │ Commerce │ │ API │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
│ POST /api/webhooks/ │ │
│ btcpay │ │
│ ───────────────────────▶│ │
│ │ │
│ │ POST /api/webhooks/ │
│ │ stripe │
│ │◀─────────────────────────
│ │ │
```
## Endpoints
| Gateway | Endpoint | Signature Header |
|---------|----------|------------------|
| BTCPay | `POST /api/webhooks/btcpay` | `BTCPay-Sig` |
| Stripe | `POST /api/webhooks/stripe` | `Stripe-Signature` |
Both endpoints:
- Rate limited: 120 requests per minute
- No authentication middleware (signature verification only)
- Return 200 for successful processing (even if event is skipped)
- Return 401 for invalid signatures
- Return 500 for processing errors (triggers gateway retry)
## BTCPay Webhooks
### Configuration
In BTCPay Server dashboard:
1. Navigate to Store Settings > Webhooks
2. Create webhook with URL: `https://yourdomain.com/api/webhooks/btcpay`
3. Select events to send
4. Copy webhook secret to `BTCPAY_WEBHOOK_SECRET`
### Event Types
| BTCPay Event | Mapped Type | Action |
|--------------|-------------|--------|
| `InvoiceCreated` | `invoice.created` | No action |
| `InvoiceReceivedPayment` | `invoice.payment_received` | Order → processing |
| `InvoiceProcessing` | `invoice.processing` | Order → processing |
| `InvoiceSettled` | `invoice.paid` | Fulfil order |
| `InvoiceExpired` | `invoice.expired` | Order → failed |
| `InvoiceInvalid` | `invoice.failed` | Order → failed |
### Processing Flow
```php
// BTCPayWebhookController::handle()
1. Verify signature
└── 401 if invalid
2. Parse event
└── Extract type, invoice ID, metadata
3. Log webhook event
└── WebhookLogger creates audit record
4. Route to handler (in transaction)
├── invoice.paid → handleSettled()
├── invoice.expired → handleExpired()
└── default → handleUnknownEvent()
5. Return response
└── 200 OK (even for skipped events)
```
### Invoice Settlement Handler
```php
protected function handleSettled(array $event): Response
{
// 1. Find order by gateway session ID
$order = Order::where('gateway', 'btcpay')
->where('gateway_session_id', $event['id'])
->first();
// 2. Skip if already paid (idempotency)
if ($order->isPaid()) {
return response('Already processed', 200);
}
// 3. Create payment record
$payment = Payment::create([
'gateway' => 'btcpay',
'gateway_payment_id' => $event['id'],
'amount' => $order->total,
'status' => 'succeeded',
// ...
]);
// 4. Fulfil order (provisions entitlements, creates invoice)
$this->commerce->fulfillOrder($order, $payment);
// 5. Send confirmation email
$this->sendOrderConfirmation($order);
return response('OK', 200);
}
```
## Stripe Webhooks
### Configuration
In Stripe Dashboard:
1. Navigate to Developers > Webhooks
2. Add endpoint: `https://yourdomain.com/api/webhooks/stripe`
3. Select events to listen for
4. Copy signing secret to `STRIPE_WEBHOOK_SECRET`
### Event Types
| Stripe Event | Action |
|--------------|--------|
| `checkout.session.completed` | Fulfil order, create subscription |
| `invoice.paid` | Renew subscription period |
| `invoice.payment_failed` | Mark past_due, trigger dunning |
| `customer.subscription.created` | Fallback (usually handled by checkout) |
| `customer.subscription.updated` | Sync status, period dates |
| `customer.subscription.deleted` | Cancel, revoke entitlements |
| `payment_method.attached` | Store payment method |
| `payment_method.detached` | Deactivate payment method |
| `payment_method.updated` | Update card details |
| `setup_intent.succeeded` | Attach payment method from setup flow |
### Checkout Completion Handler
```php
protected function handleCheckoutCompleted(array $event): Response
{
$session = $event['raw']['data']['object'];
$orderId = $session['metadata']['order_id'];
// Find and validate order
$order = Order::find($orderId);
if (!$order || $order->isPaid()) {
return response('Already processed', 200);
}
// Create payment record
$payment = Payment::create([
'gateway' => 'stripe',
'gateway_payment_id' => $session['payment_intent'],
'amount' => $session['amount_total'] / 100,
'status' => 'succeeded',
]);
// Handle subscription if present
if (!empty($session['subscription'])) {
$this->createOrUpdateSubscriptionFromSession($order, $session);
}
// Fulfil order
$this->commerce->fulfillOrder($order, $payment);
return response('OK', 200);
}
```
### Subscription Invoice Handler
```php
protected function handleInvoicePaid(array $event): Response
{
$invoice = $event['raw']['data']['object'];
$subscriptionId = $invoice['subscription'];
// Find subscription
$subscription = Subscription::where('gateway', 'stripe')
->where('gateway_subscription_id', $subscriptionId)
->first();
// Update period dates
$subscription->renew(
Carbon::createFromTimestamp($invoice['period_start']),
Carbon::createFromTimestamp($invoice['period_end'])
);
// Create payment record
$payment = Payment::create([...]);
// Create local invoice
$this->invoiceService->createForRenewal($subscription->workspace, ...);
return response('OK', 200);
}
```
## Signature Verification
### BTCPay
```php
// BTCPayGateway::verifyWebhookSignature()
$providedSignature = $signature;
if (str_starts_with($signature, 'sha256=')) {
$providedSignature = substr($signature, 7);
}
$expectedSignature = hash_hmac('sha256', $payload, $this->webhookSecret);
return hash_equals($expectedSignature, $providedSignature);
```
### Stripe
```php
// StripeGateway::verifyWebhookSignature()
try {
\Stripe\Webhook::constructEvent($payload, $signature, $this->webhookSecret);
return true;
} catch (\Exception $e) {
return false;
}
```
## Webhook Logging
All webhook events are logged via `WebhookLogger`:
```php
// Start logging
$this->webhookLogger->startFromParsedEvent('btcpay', $event, $payload, $request);
// Link to entities for audit trail
$this->webhookLogger->linkOrder($order);
$this->webhookLogger->linkSubscription($subscription);
// Mark outcome
$this->webhookLogger->success($response);
$this->webhookLogger->fail($errorMessage, $statusCode);
$this->webhookLogger->skip($reason);
```
Logged data includes:
- Event type and ID
- Raw payload (encrypted)
- IP address and user agent
- Processing outcome
- Related order/subscription IDs
## Error Handling
### Gateway Retries
Both gateways retry failed webhooks:
| Gateway | Retry Schedule | Max Attempts |
|---------|---------------|--------------|
| BTCPay | Exponential backoff | Configurable |
| Stripe | Exponential over 3 days | ~20 attempts |
**Important:** Return `200 OK` even for events that are skipped or already processed. Only return `500` for actual processing errors that should be retried.
### Transaction Safety
All webhook handlers wrap processing in database transactions:
```php
try {
$response = DB::transaction(function () use ($event) {
return match ($event['type']) {
'invoice.paid' => $this->handleSettled($event),
// ...
};
});
return $response;
} catch (\Exception $e) {
Log::error('Webhook processing error', [...]);
return response('Processing error', 500);
}
```
## Testing Webhooks
### Local Development
Use gateway CLI tools to send test webhooks:
**BTCPay:**
```bash
# Trigger test webhook from BTCPay admin
# Or use btcpay-cli if available
```
**Stripe:**
```bash
# Forward webhooks to local
stripe listen --forward-to localhost:8000/api/webhooks/stripe
# Trigger specific event
stripe trigger checkout.session.completed
```
### Automated Tests
See `tests/Feature/WebhookTest.php` for webhook handler tests:
```php
test('btcpay settled webhook fulfils order', function () {
$order = Order::factory()->create(['status' => 'processing']);
$payload = json_encode([
'type' => 'InvoiceSettled',
'invoiceId' => $order->gateway_session_id,
// ...
]);
$signature = hash_hmac('sha256', $payload, config('commerce.gateways.btcpay.webhook_secret'));
$response = $this->postJson('/api/webhooks/btcpay', [], [
'BTCPay-Sig' => $signature,
'Content-Type' => 'application/json',
]);
$response->assertStatus(200);
expect($order->fresh()->status)->toBe('paid');
});
```
## Troubleshooting
### Common Issues
**401 Invalid Signature**
- Check webhook secret matches environment variable
- Ensure raw payload is used (not parsed JSON)
- Verify signature header name is correct
**Order Not Found**
- Check `gateway_session_id` matches invoice ID
- Verify order was created before webhook arrived
- Check for typos in metadata passed to gateway
**Duplicate Processing**
- Normal behavior if webhook is retried
- Order state check (`isPaid()`) prevents double fulfillment
- Consider adding idempotency key storage
### Debug Logging
Enable verbose logging temporarily:
```php
// In webhook controller
Log::debug('Webhook payload', [
'type' => $event['type'],
'id' => $event['id'],
'raw' => $event['raw'],
]);
```
### Webhook Event Viewer
Query logged events:
```sql
SELECT * FROM commerce_webhook_events
WHERE event_type = 'InvoiceSettled'
AND status = 'failed'
ORDER BY created_at DESC
LIMIT 10;
```

View file

@ -0,0 +1,422 @@
---
title: Architecture
description: Technical architecture of the core-content package
updated: 2026-01-29
---
# Architecture
The `core-content` package provides headless CMS functionality for the Host UK platform. It handles content management, AI-powered generation, revision history, webhooks for external CMS integration, and search capabilities.
## Package Overview
**Namespace:** `Core\Mod\Content\`
**Entry Point:** `Boot.php` (Laravel Service Provider)
**Dependencies:**
- `core-php` (Foundation framework, events)
- `core-tenant` (Workspaces, users, entitlements)
- Optional: `core-agentic` (AI services for content generation)
- Optional: `core-mcp` (MCP tool handlers)
## Directory Structure
```
core-content/
├── Boot.php # Service provider with event listeners
├── config.php # Package configuration
├── Models/ # Eloquent models (10 models)
├── Services/ # Business logic services
├── Controllers/ # API and web controllers
│ └── Api/ # REST API controllers
├── Jobs/ # Queue jobs
├── Mcp/ # MCP tool handlers
│ └── Handlers/ # Individual MCP tools
├── Concerns/ # Traits
├── Console/ # Artisan commands
│ └── Commands/ # Command implementations
├── Enums/ # PHP enums
├── Migrations/ # Database migrations
├── Observers/ # Model observers
├── routes/ # Route definitions
├── View/ # Livewire components and Blade views
│ ├── Modal/ # Livewire components
│ └── Blade/ # Blade templates
├── tests/ # Test suite
└── docs/ # Documentation
```
## Core Concepts
### Content Items
The primary content model. Supports multiple content types and sources:
```php
// Content types (where content originates)
enum ContentType: string {
case NATIVE = 'native'; // Created in Host Hub editor
case HOSTUK = 'hostuk'; // Alias for native (backwards compat)
case SATELLITE = 'satellite'; // Per-service content
case WORDPRESS = 'wordpress'; // Legacy synced content
}
```
Content items belong to workspaces and have:
- Title, slug, excerpt, content (HTML/Markdown/JSON)
- Status (draft, publish, future, private, pending)
- Author and last editor tracking
- Revision history
- Taxonomy (categories, tags)
- SEO metadata
- Preview tokens for sharing unpublished content
- CDN cache invalidation tracking
### Content Briefs
Briefs drive AI-powered content generation. They define what content to create:
```php
// Brief content types (what to generate)
enum BriefContentType: string {
case HELP_ARTICLE = 'help_article'; // Documentation
case BLOG_POST = 'blog_post'; // Blog articles
case LANDING_PAGE = 'landing_page'; // Marketing pages
case SOCIAL_POST = 'social_post'; // Social media
}
```
Brief workflow: `pending` -> `queued` -> `generating` -> `review` -> `published`
### Revisions
Every content change creates an immutable revision snapshot. Revisions support:
- Change type tracking (edit, autosave, restore, publish)
- Word/character count tracking
- Side-by-side diff comparison with LCS algorithm
- Configurable retention policies (max count, max age)
## Service Layer
### AIGatewayService
Orchestrates two-stage AI content generation:
1. **Stage 1: Draft (Gemini)** - Fast, cost-effective initial generation
2. **Stage 2: Refine (Claude)** - Quality refinement and brand voice alignment
```php
$gateway = app(AIGatewayService::class);
// Two-stage pipeline
$result = $gateway->generateAndRefine($brief);
// Or individual stages
$draft = $gateway->generateDraft($brief);
$refined = $gateway->refineDraft($brief, $draftContent);
// Direct Claude generation (skip Gemini)
$content = $gateway->generateDirect($brief);
```
### ContentSearchService
Full-text search with multiple backend support:
```php
// Backends (configured via CONTENT_SEARCH_BACKEND)
const BACKEND_DATABASE = 'database'; // LIKE queries with relevance
const BACKEND_SCOUT_DATABASE = 'scout_database'; // Laravel Scout
const BACKEND_MEILISEARCH = 'meilisearch'; // Laravel Scout + Meilisearch
```
Features:
- Relevance scoring (title > slug > excerpt > content)
- Filters: type, status, category, tag, date range, content_type
- Autocomplete suggestions
- Re-indexing support for Scout backends
### WebhookRetryService
Handles failed webhook processing with exponential backoff:
```
Retry intervals: 1m, 5m, 15m, 1h, 4h
Max retries: 5 (configurable per webhook)
```
### ContentRender
Public-facing content renderer with caching:
- Homepage, blog listing, post, page rendering
- Cache TTL: 1 hour production, 1 minute development
- Cache key sanitisation for special characters
### CdnPurgeService
CDN cache invalidation via Bunny CDN:
- Triggered by ContentItemObserver on publish/update
- URL-based and tag-based purging
- Workspace-level cache clearing
## Event-Driven Architecture
The package uses the event-driven module loading pattern from `core-php`:
```php
class Boot extends ServiceProvider
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
ApiRoutesRegistering::class => 'onApiRoutes',
ConsoleBooting::class => 'onConsole',
McpToolsRegistering::class => 'onMcpTools',
];
}
```
Handlers register:
- **Web Routes:** Public blog, help pages, content preview
- **API Routes:** REST API for briefs, media, search, generation
- **Console:** Artisan commands for scheduling, pruning
- **MCP Tools:** AI agent content management tools
## API Structure
### Authenticated Endpoints (Session or API Key)
```
# Content Briefs
GET /api/content/briefs # List briefs
POST /api/content/briefs # Create brief
GET /api/content/briefs/{id} # Get brief
PUT /api/content/briefs/{id} # Update brief
DELETE /api/content/briefs/{id} # Delete brief
POST /api/content/briefs/bulk # Bulk create
GET /api/content/briefs/next # Next ready for processing
# AI Generation (rate limited: 10/min)
POST /api/content/generate/draft # Generate draft (Gemini)
POST /api/content/generate/refine # Refine draft (Claude)
POST /api/content/generate/full # Full pipeline
POST /api/content/generate/social # Social posts from content
# Content Search (rate limited: 60/min)
GET /api/content/search # Full-text search
GET /api/content/search/suggest # Autocomplete
GET /api/content/search/info # Backend info
POST /api/content/search/reindex # Trigger re-index
# Revisions
GET /api/content/items/{id}/revisions # List revisions
GET /api/content/revisions/{id} # Get revision
POST /api/content/revisions/{id}/restore # Restore revision
GET /api/content/revisions/{id}/compare/{other} # Compare
# Preview
POST /api/content/items/{id}/preview/generate # Generate preview link
DELETE /api/content/items/{id}/preview/revoke # Revoke preview link
```
### Public Endpoints
```
# Webhooks (signature verified, no auth)
POST /api/content/webhooks/{endpoint} # Receive external webhooks
# Web Routes
GET /blog # Blog listing
GET /blog/{slug} # Blog post
GET /help # Help centre
GET /help/{slug} # Help article
GET /content/preview/{id} # Preview content
```
## Rate Limiting
Defined in `Boot::configureRateLimiting()`:
| Limiter | Authenticated | Unauthenticated |
|---------|---------------|-----------------|
| `content-generate` | 10/min per user/workspace | 2/min per IP |
| `content-briefs` | 30/min per user | 5/min per IP |
| `content-webhooks` | 60/min per endpoint | 30/min per IP |
| `content-search` | Configurable (default 60/min) | 20/min per IP |
## MCP Tools
Seven MCP tools for AI agent integration:
| Tool | Description |
|------|-------------|
| `content_list` | List content items with filters |
| `content_read` | Read content by ID or slug |
| `content_search` | Full-text search |
| `content_create` | Create new content |
| `content_update` | Update existing content |
| `content_delete` | Soft delete content |
| `content_taxonomies` | List categories and tags |
All tools:
- Require workspace resolution
- Check entitlements (`content.mcp_access`, `content.items`)
- Log actions to MCP session
- Return structured responses
## Data Flow
### Content Creation via MCP
```
Agent Request
ContentCreateHandler::handle()
resolveWorkspace() → Workspace model
checkEntitlement() → EntitlementService
ContentItem::create()
createRevision() → ContentRevision
recordUsage() → EntitlementService
Response with content ID
```
### Webhook Processing
```
External CMS
POST /api/content/webhooks/{endpoint}
ContentWebhookController::receive()
Verify signature → ContentWebhookEndpoint::verifySignature()
Check type allowed → ContentWebhookEndpoint::isTypeAllowed()
Create ContentWebhookLog
Dispatch ProcessContentWebhook job
Job::handle()
Process based on event type (wordpress.*, cms.*, generic.*)
Create/Update/Delete ContentItem
Mark log completed
```
### AI Generation Pipeline
```
ContentBrief
GenerateContentJob dispatched
Stage 1: AIGatewayService::generateDraft()
GeminiService::generate() → Draft content
Brief::markDraftComplete()
Stage 2: AIGatewayService::refineDraft()
ClaudeService::generate() → Refined content
Brief::markRefined()
AIUsage records created for each stage
```
## Configuration
Key settings in `config.php`:
```php
return [
'generation' => [
'default_timeout' => env('CONTENT_GENERATION_TIMEOUT', 300),
'timeouts' => [
'help_article' => 180,
'blog_post' => 240,
'landing_page' => 300,
'social_post' => 60,
],
'max_retries' => 3,
'backoff' => [30, 60, 120],
],
'revisions' => [
'max_per_item' => env('CONTENT_MAX_REVISIONS', 50),
'max_age_days' => 180,
'preserve_published' => true,
],
'cache' => [
'ttl' => env('CONTENT_CACHE_TTL', 3600),
'prefix' => 'content:render',
],
'search' => [
'backend' => env('CONTENT_SEARCH_BACKEND', 'database'),
'min_query_length' => 2,
'max_per_page' => 50,
'default_per_page' => 20,
'rate_limit' => 60,
],
];
```
## Database Schema
### Primary Tables
| Table | Purpose |
|-------|---------|
| `content_items` | Content storage (posts, pages) |
| `content_revisions` | Version history |
| `content_taxonomies` | Categories and tags |
| `content_item_taxonomy` | Pivot table |
| `content_media` | Media attachments |
| `content_authors` | Author profiles |
| `content_briefs` | AI generation briefs |
| `content_tasks` | Scheduled content tasks |
| `content_webhook_endpoints` | Webhook configurations |
| `content_webhook_logs` | Webhook processing logs |
| `ai_usage` | AI API usage tracking |
| `prompts` | AI prompt templates |
| `prompt_versions` | Prompt version history |
### Key Indexes
- `content_items`: Composite indexes on `(workspace_id, slug, type)`, `(workspace_id, status, type)`, `(workspace_id, status, content_type)`
- `content_revisions`: Index on `(content_item_id, revision_number)`
- `content_webhook_logs`: Index on `(workspace_id, status)`, `(status, created_at)`
## Extension Points
### Adding New Content Types
1. Add value to `ContentType` enum
2. Update `ContentType::isNative()` if applicable
3. Add any type-specific scopes to `ContentItem`
### Adding New AI Generation Types
1. Add value to `BriefContentType` enum
2. Add timeout to `config.php` generation.timeouts
3. Add prompt in `AIGatewayService::getDraftSystemPrompt()`
### Adding New Webhook Event Types
1. Add to `ContentWebhookEndpoint::ALLOWED_TYPES`
2. Add handler in `ProcessContentWebhook::processWordPress()` or `processCms()`
3. Add event type mapping in `ContentWebhookController::normaliseEventType()`
### Adding New MCP Tools
1. Create handler in `Mcp/Handlers/` implementing `McpToolHandler`
2. Define `schema()` with tool name, description, input schema
3. Implement `handle()` with workspace resolution and entitlement checks
4. Register in `Boot::onMcpTools()`

View file

@ -0,0 +1,389 @@
---
title: Security
description: Security considerations and audit notes for core-content
updated: 2026-01-29
---
# Security
This document covers security considerations, known risks, and recommended mitigations for the `core-content` package.
## Authentication and Authorisation
### API Authentication
The content API supports two authentication methods:
1. **Session Authentication** (`auth` middleware)
- For browser-based access
- CSRF protection via Laravel's standard middleware
2. **API Key Authentication** (`api.auth` middleware)
- For programmatic access
- Keys prefixed with `hk_`
- Scope enforcement via `api.scope.enforce` middleware
### Webhook Authentication
Webhooks use HMAC signature verification instead of session/API key auth:
```php
// Signature verification in ContentWebhookEndpoint
public function verifySignature(string $payload, ?string $signature): bool
{
$expectedSignature = hash_hmac('sha256', $payload, $this->secret);
return hash_equals($expectedSignature, $signature);
}
```
**Supported signature headers:**
- `X-Signature`
- `X-Hub-Signature-256` (GitHub format)
- `X-WP-Webhook-Signature` (WordPress format)
- `X-Content-Signature`
- `Signature`
### MCP Tool Authentication
MCP tools authenticate via the MCP session context. Workspace access is verified through:
- Workspace resolution (by slug or ID)
- Entitlement checks (`content.mcp_access`, `content.items`)
## Known Security Considerations
### HIGH: HTML Sanitisation Fallback
**Location:** `Models/ContentItem.php:333-351`
**Issue:** The `getSanitisedContent()` method falls back to `strip_tags()` if HTMLPurifier is unavailable. This is insufficient for XSS protection.
```php
// Current fallback (insufficient)
$allowedTags = '<p><br><strong>...<a>...';
return strip_tags($content, $allowedTags);
```
**Risk:** XSS attacks via crafted HTML in content body.
**Mitigation:**
1. Ensure HTMLPurifier is installed in production
2. Add package check in boot to fail loudly if missing
3. Consider using `voku/anti-xss` as a lighter alternative
### HIGH: Webhook Signature Optional
**Location:** `Models/ContentWebhookEndpoint.php:205-210`
**Issue:** When no secret is configured, signature verification is skipped:
```php
if (empty($this->secret)) {
return true; // Accepts all requests
}
```
**Risk:** Unauthenticated webhook injection if endpoint has no secret.
**Mitigation:**
1. Require secrets for all production endpoints
2. Add explicit `allow_unsigned` flag if intentional
3. Log warning when unsigned webhooks are accepted
4. Rate limit unsigned endpoints more aggressively
### MEDIUM: Workspace Access in MCP Handlers
**Location:** `Mcp/Handlers/*.php`
**Issue:** Workspace resolution allows lookup by ID:
```php
return Workspace::where('slug', $slug)
->orWhere('id', $slug)
->first();
```
**Risk:** If an attacker knows a workspace ID, they could potentially access content without being a workspace member.
**Mitigation:**
1. Always verify workspace membership after resolution
2. Use entitlement checks (already present but verify coverage)
3. Consider removing ID-based lookup for MCP
### MEDIUM: Preview Token Enumeration
**Location:** `Controllers/ContentPreviewController.php`
**Issue:** No rate limiting on preview token generation endpoint. An attacker could probe for valid content IDs.
**Mitigation:**
1. Add rate limiting (30/min per user)
2. Use constant-time responses regardless of content existence
3. Consider using UUIDs instead of sequential IDs for preview URLs
### LOW: Webhook Payload Content Types
**Location:** `Jobs/ProcessContentWebhook.php:288-289`
**Issue:** Content type from external webhook is assigned directly:
```php
$contentItem->content_type = ContentType::NATIVE;
```
**Risk:** External systems could potentially inject invalid content types.
**Mitigation:**
1. Validate against `ContentType` enum
2. Default to a safe type if validation fails
3. Log invalid types for monitoring
## Input Validation
### API Request Validation
All API controllers use Laravel's validation:
```php
$validated = $request->validate([
'q' => 'required|string|min:2|max:500',
'type' => 'nullable|string|in:post,page',
'status' => 'nullable',
// ...
]);
```
**Validated inputs:**
- Search queries (min/max length, string type)
- Content types (enum validation)
- Pagination (min/max values)
- Date ranges (date format, logical order)
### MCP Input Validation
MCP handlers validate via JSON schema:
```php
'inputSchema' => [
'type' => 'object',
'properties' => [
'workspace' => ['type' => 'string'],
'title' => ['type' => 'string'],
'type' => ['type' => 'string', 'enum' => ['post', 'page']],
],
'required' => ['workspace', 'title'],
]
```
### Webhook Payload Validation
Webhook payloads undergo:
- JSON decode validation
- Event type normalisation
- Content ID extraction with fallbacks
**Note:** Payload content is stored in JSON column without full validation. Processing logic handles missing/invalid fields gracefully.
## Rate Limiting
### Configured Limiters
| Endpoint | Auth | Unauthenticated | Key |
|----------|------|-----------------|-----|
| AI Generation | 10/min | 2/min | `content-generate` |
| Brief Creation | 30/min | 5/min | `content-briefs` |
| Webhooks | 60/min | 30/min | `content-webhooks` |
| Search | 60/min | 20/min | `content-search` |
### Rate Limit Bypass Risks
1. **IP Spoofing:** Ensure `X-Forwarded-For` handling is configured correctly
2. **Workspace Switching:** Workspace-based limits should use user ID as fallback
3. **API Key Sharing:** Each key should have independent limits
## Data Protection
### Sensitive Data Handling
**Encrypted at rest:**
- `ContentWebhookEndpoint.secret` (cast to `encrypted`)
- `ContentWebhookEndpoint.previous_secret` (cast to `encrypted`)
**Hidden from serialisation:**
- Webhook secrets (via `$hidden` property)
### PII Considerations
Content may contain PII in:
- Article body content
- Author information
- Webhook payloads
**Recommendations:**
1. Implement content retention policies
2. Add GDPR data export/deletion support
3. Log access to PII-containing content
## Webhook Security
### Circuit Breaker
Endpoints automatically disable after 10 consecutive failures:
```php
const MAX_FAILURES = 10;
public function incrementFailureCount(): void
{
$this->increment('failure_count');
if ($this->failure_count >= self::MAX_FAILURES) {
$this->update(['is_enabled' => false]);
}
}
```
### Secret Rotation
Grace period support for secret rotation:
```php
public function isInGracePeriod(): bool
{
// Accepts both current and previous secret during grace
}
```
Default grace period: 24 hours
### Allowed Event Types
Endpoints can restrict which event types they accept:
```php
const ALLOWED_TYPES = [
'wordpress.post_created',
'wordpress.post_updated',
// ...
'generic.payload',
];
```
Wildcard support: `wordpress.*` matches all WordPress events.
## Content Security
### XSS Prevention
1. **Input:** Content stored as-is to preserve formatting
2. **Output:** `getSanitisedContent()` for public rendering
3. **Admin:** Trusted content displayed with proper escaping
**Blade template guidelines:**
- Use `{{ $title }}` for plain text (auto-escaped)
- Use `{!! $content !!}` only for sanitised HTML
- Comments document which fields need which treatment
### SQL Injection
All database queries use:
- Eloquent ORM (parameterised queries)
- Query builder with bindings
- No raw SQL with user input
### CSRF Protection
Web routes include CSRF middleware automatically. API routes exempt (use API key auth).
## Audit Logging
### Logged Events
- Webhook receipt and processing
- AI generation requests and results
- Content creation/update/deletion via MCP
- CDN cache purges
- Authentication failures
### Log Levels
| Event | Level |
|-------|-------|
| Webhook signature failure | WARNING |
| Circuit breaker triggered | WARNING |
| Processing failure | ERROR |
| Successful operations | INFO |
| Skipped operations | DEBUG |
## Recommendations
### Immediate (P1)
1. [ ] Require HTMLPurifier or equivalent in production
2. [ ] Make webhook signature verification mandatory
3. [ ] Add rate limiting to preview generation
4. [ ] Validate content_type from webhook payloads
### Short-term (P2)
1. [ ] Add comprehensive audit logging
2. [ ] Implement content access logging
3. [ ] Add IP allowlisting option for webhooks
4. [ ] Create security-focused test suite
### Long-term (P3+)
1. [ ] Implement content encryption at rest option
2. [ ] Add GDPR compliance features
3. [ ] Create security monitoring dashboard
4. [ ] Add anomaly detection for webhook patterns
## Security Testing
### Manual Testing Checklist
```
[ ] Verify webhook signature rejection with invalid signature
[ ] Test rate limiting enforcement
[ ] Confirm XSS payloads are sanitised
[ ] Verify workspace isolation in API responses
[ ] Test preview token expiration
[ ] Verify CSRF protection on web routes
[ ] Test SQL injection attempts in search
[ ] Verify file type validation on media uploads
```
### Automated Testing
```bash
# Run security-focused tests
./vendor/bin/pest --filter=Security
# Check for common vulnerabilities
./vendor/bin/pint --test # Code style (includes some security patterns)
```
## Incident Response
### Webhook Compromise
1. Disable affected endpoint
2. Rotate all secrets
3. Review webhook logs for suspicious patterns
4. Regenerate secrets for all endpoints
### Content Injection
1. Identify affected content items
2. Restore from revision history
3. Review webhook source
4. Add additional validation
### API Key Leak
1. Revoke compromised key
2. Review access logs
3. Generate new key with reduced scope
4. Monitor for unauthorised access
## Contact
Security issues should be reported to the security team. Do not create public issues for security vulnerabilities.

View file

@ -0,0 +1,390 @@
---
title: Architecture
description: Technical architecture of the core-developer package
updated: 2026-01-29
---
# Architecture
The `core-developer` package provides administrative developer tools for the Host UK platform. It is designed exclusively for "Hades" tier users (god-mode access) and includes debugging, monitoring, and server management capabilities.
## Package Overview
| Aspect | Detail |
|--------|--------|
| Namespace | `Core\Developer\` |
| Type | L1 Module (Laravel Package) |
| Dependencies | `host-uk/core`, `host-uk/core-admin` |
| PHP Version | 8.2+ |
| Laravel Version | 11.x / 12.x |
| Livewire Version | 3.x / 4.x |
## Directory Structure
```
src/
├── Boot.php # Service provider & event handlers
├── Controllers/
│ └── DevController.php # REST API endpoints
├── Concerns/
│ └── RemoteServerManager.php # SSH connection trait
├── Console/Commands/
│ └── CopyDeviceFrames.php # Asset management command
├── Data/
│ └── RouteTestResult.php # DTO for route test results
├── Exceptions/
│ └── SshConnectionException.php
├── Lang/
│ └── en_GB/developer.php # Translations
├── Listeners/
│ └── SetHadesCookie.php # Login event listener
├── Middleware/
│ ├── ApplyIconSettings.php # Icon preferences from cookies
│ └── RequireHades.php # Authorization middleware
├── Migrations/
│ └── 0001_01_01_000001_create_developer_tables.php
├── Models/
│ └── Server.php # SSH server model
├── Providers/
│ ├── HorizonServiceProvider.php
│ └── TelescopeServiceProvider.php
├── Routes/
│ └── admin.php # Route definitions
├── Services/
│ ├── LogReaderService.php # Log file parsing
│ └── RouteTestService.php # Route testing logic
├── Tests/
│ └── UseCase/
│ └── DevToolsBasic.php # Feature tests
└── View/
├── Blade/
│ └── admin/ # Blade templates
│ ├── activity-log.blade.php
│ ├── cache.blade.php
│ ├── database.blade.php
│ ├── logs.blade.php
│ ├── route-inspector.blade.php
│ ├── routes.blade.php
│ └── servers.blade.php
└── Modal/
└── Admin/ # Livewire components
├── ActivityLog.php
├── Cache.php
├── Database.php
├── Logs.php
├── RouteInspector.php
├── Routes.php
└── Servers.php
```
## Event-Driven Module Loading
The module uses the Core Framework's event-driven lazy loading pattern. The `Boot` class declares which events it listens to:
```php
public static array $listens = [
AdminPanelBooting::class => 'onAdminPanel',
ConsoleBooting::class => 'onConsole',
];
```
This ensures routes, views, and commands are only registered when the admin panel or console is actually used.
### Lifecycle Events
| Event | Handler | What Happens |
|-------|---------|--------------|
| `AdminPanelBooting` | `onAdminPanel()` | Registers views, routes, Pulse override |
| `ConsoleBooting` | `onConsole()` | Registers Artisan commands |
## Core Components
### 1. Livewire Admin Pages
All admin pages are full-page Livewire components using attribute-based configuration:
```php
#[Title('Application Logs')]
#[Layout('hub::admin.layouts.app')]
class Logs extends Component
```
Each component:
- Checks Hades access in `mount()`
- Uses `developer::admin.{name}` view namespace
- Has corresponding Blade template in `View/Blade/admin/`
### 2. API Controller
`DevController` provides REST endpoints for:
- `/hub/api/dev/logs` - Recent log entries
- `/hub/api/dev/routes` - Route listing
- `/hub/api/dev/session` - Session/request info
- `/hub/api/dev/clear/{type}` - Cache clearing
All endpoints are protected by `RequireHades` middleware and rate limiting.
### 3. Services
**LogReaderService**
- Memory-efficient log reading (reads from end of file)
- Parses Laravel log format
- Automatic sensitive data redaction
- Multi-log file support (daily/single channels)
**RouteTestService**
- Route discovery and formatting
- Request building with parameters
- In-process request execution
- Response formatting and metrics
### 4. RemoteServerManager Trait
Provides SSH connection management for classes that need remote server access:
```php
class DeployApplication implements ShouldQueue
{
use RemoteServerManager;
public function handle(): void
{
$this->withConnection($this->server, function () {
$this->run('cd /var/www && git pull');
});
}
}
```
Key methods:
- `connect()` / `disconnect()` - Connection lifecycle
- `withConnection()` - Guaranteed cleanup pattern
- `run()` / `runMany()` - Command execution
- `fileExists()` / `readFile()` / `writeFile()` - File operations
- `getDiskUsage()` / `getMemoryUsage()` - Server stats
## Data Flow
### Admin Page Request
```
Browser Request
Laravel Router → /hub/dev/logs
Livewire Component (Logs.php)
mount() → checkHadesAccess()
loadLogs() → LogReaderService
render() → developer::admin.logs
Response (HTML)
```
### API Request
```
Browser/JS Request
Laravel Router → /hub/api/dev/logs
RequireHades Middleware
Rate Limiter (throttle:dev-logs)
DevController::logs()
LogReaderService
Response (JSON)
```
### SSH Connection
```
Servers Component
testConnection($serverId)
Server::findOrFail()
Write temp key file
Process::run(['ssh', ...])
Parse result
Update server status
Clean up temp file
```
## Database Schema
### servers table
| Column | Type | Description |
|--------|------|-------------|
| id | bigint | Primary key |
| workspace_id | bigint | FK to workspaces |
| name | varchar(128) | Display name |
| ip | varchar(45) | IPv4/IPv6 address |
| port | smallint | SSH port (default 22) |
| user | varchar(64) | SSH username |
| private_key | text | Encrypted SSH key |
| status | varchar(32) | pending/connected/failed |
| last_connected_at | timestamp | Last successful connection |
| timestamps | | created_at, updated_at |
| soft_deletes | | deleted_at |
Indexes:
- `workspace_id`
- `(workspace_id, status)` composite
## Admin Menu Structure
The module registers a "Dev Tools" menu group with these items:
```
Dev Tools (admin group, priority 80)
├── Logs → /hub/dev/logs
├── Activity → /hub/dev/activity
├── Servers → /hub/dev/servers
├── Database → /hub/dev/database
├── Routes → /hub/dev/routes
├── Route Inspector → /hub/dev/route-inspector
└── Cache → /hub/dev/cache
```
The menu is only visible to users with `admin` flag (Hades tier).
## Rate Limiting
API endpoints have rate limits configured in `Boot::configureRateLimiting()`:
| Limiter | Limit | Purpose |
|---------|-------|---------|
| `dev-cache-clear` | 10/min | Prevent rapid cache clears |
| `dev-logs` | 30/min | Log reading |
| `dev-routes` | 30/min | Route listing |
| `dev-session` | 60/min | Session info |
Rate limits are per-user (or per-IP for unauthenticated requests).
## Third-Party Integrations
### Laravel Telescope
Custom `TelescopeServiceProvider` configures:
- Gate for Hades-only access in production
- Entry filtering (errors, failed jobs in production)
- Sensitive header/parameter hiding
### Laravel Horizon
Custom `HorizonServiceProvider` configures:
- Gate for Hades-only access
- Notification routing from config (email, SMS, Slack)
### Laravel Pulse
Custom Pulse dashboard view override at `View/Blade/vendor/pulse/dashboard.blade.php`.
## Configuration
The module expects these config keys (should be in `config/developer.php`):
```php
return [
// Hades cookie token
'hades_token' => env('HADES_TOKEN'),
// SSH settings
'ssh' => [
'connection_timeout' => 30,
'command_timeout' => 60,
],
// Horizon notifications
'horizon' => [
'mail_to' => env('HORIZON_MAIL_TO'),
'sms_to' => env('HORIZON_SMS_TO'),
'slack_webhook' => env('HORIZON_SLACK_WEBHOOK'),
'slack_channel' => env('HORIZON_SLACK_CHANNEL', '#alerts'),
],
];
```
## Extension Points
### Adding New Admin Pages
1. Create Livewire component in `View/Modal/Admin/`
2. Create Blade view in `View/Blade/admin/`
3. Add route in `Routes/admin.php`
4. Add menu item in `Boot::adminMenuItems()`
5. Add translations in `Lang/en_GB/developer.php`
### Adding New API Endpoints
1. Add method to `DevController`
2. Add route in `Routes/admin.php` API group
3. Create rate limiter in `Boot::configureRateLimiting()`
4. Apply `throttle:limiter-name` middleware
### Using RemoteServerManager
```php
use Core\Developer\Concerns\RemoteServerManager;
class MyJob
{
use RemoteServerManager;
public function handle(Server $server): void
{
$this->withConnection($server, function () {
// Commands executed on remote server
$result = $this->run('whoami');
// ...
});
}
}
```
## Performance Considerations
1. **Log Reading** - Uses backwards reading to avoid loading entire log into memory. Configurable `maxBytes` limit.
2. **Route Caching** - Routes are computed once per request. The `RouteInspector` uses `#[Computed(cache: true)]` for route list.
3. **Query Log** - Enabled only in local environment (`Boot::boot()`).
4. **SSH Connections** - Always disconnect via `withConnection()` pattern to prevent resource leaks.
## Dependencies
### Composer Requirements
- `host-uk/core` - Core framework
- `host-uk/core-admin` - Admin panel infrastructure
- `phpseclib3` - SSH connections (via RemoteServerManager)
- `spatie/laravel-activitylog` - Activity logging
### Frontend Dependencies
- Flux UI components
- Tailwind CSS
- Livewire 3.x
## Testing Strategy
Tests use Pest syntax and focus on:
- Page rendering and content
- Authorization enforcement
- API endpoint behaviour
- Service logic
Test database: SQLite in-memory with Telescope/Pulse disabled.

View file

@ -0,0 +1,269 @@
---
title: Security
description: Security considerations and audit notes for core-developer
updated: 2026-01-29
---
# Security Considerations
The `core-developer` package provides powerful administrative capabilities that require careful security controls. This document outlines the security model, known risks, and mitigation strategies.
## Threat Model
### Assets Protected
1. **Application logs** - May contain tokens, passwords, PII in error messages
2. **Database access** - Read-only query execution against production data
3. **SSH keys** - Encrypted private keys for server connections
4. **Cache data** - Application cache, session data, config cache
5. **Route information** - Full application route structure
### Threat Actors
1. **Unauthorized users** - Non-Hades users attempting to access dev tools
2. **Compromised Hades account** - Attacker with valid Hades credentials
3. **SSRF/Injection** - Attacker manipulating dev tools to access internal resources
4. **Data exfiltration** - Extracting sensitive data via dev tools
## Authorization Model
### Hades Tier Requirement
All developer tools require "Hades" access, verified via the `isHades()` method on the User model. This is enforced at multiple layers:
| Layer | Implementation | File |
|-------|----------------|------|
| Middleware | `RequireHades::handle()` | `src/Middleware/RequireHades.php` |
| Component | `checkHadesAccess()` in `mount()` | All Livewire components |
| API | Controller `authorize()` calls | `src/Controllers/DevController.php` |
| Menu | `admin` flag filtering | `src/Boot.php` |
### Defence in Depth
The authorization is intentionally redundant:
- API routes use `RequireHades` middleware
- Livewire components check in `mount()`
- Some controller methods call `$this->authorize()`
This ensures access is blocked even if one layer fails.
### Known Issue: Test Environment
Tests currently pass without setting Hades tier on the test user. This suggests authorization may not be properly enforced in the test environment. See TODO.md for remediation.
## Data Protection
### Log Redaction
The `LogReaderService` automatically redacts sensitive patterns before displaying logs:
| Pattern | Replacement |
|---------|-------------|
| Stripe API keys | `[STRIPE_KEY_REDACTED]` |
| GitHub tokens | `[GITHUB_TOKEN_REDACTED]` |
| Bearer tokens | `Bearer [TOKEN_REDACTED]` |
| API keys/secrets | `[KEY_REDACTED]` / `[REDACTED]` |
| AWS credentials | `[AWS_KEY_REDACTED]` / `[AWS_SECRET_REDACTED]` |
| Database URLs | Connection strings with `[USER]:[PASS]` |
| Email addresses | Partial: `jo***@example.com` |
| IP addresses | Partial: `192.168.xxx.xxx` |
| Credit card numbers | `[CARD_REDACTED]` |
| JWT tokens | `[JWT_REDACTED]` |
| Private keys | `[PRIVATE_KEY_REDACTED]` |
**Limitation**: Patterns are regex-based and may not catch all sensitive data. Custom application secrets with non-standard formats will not be redacted.
### SSH Key Storage
Server private keys are:
- Encrypted at rest using Laravel's `encrypted` cast
- Hidden from serialization (`$hidden` array)
- Never exposed in API responses or views
- Stored in `text` column (supports long keys)
### Database Query Tool
The database query component restricts access to read-only operations:
```php
protected const ALLOWED_STATEMENTS = ['SELECT', 'SHOW', 'DESCRIBE', 'EXPLAIN'];
```
**Known Risk**: The current implementation only checks the first word, which does not prevent:
- Stacked queries: `SELECT 1; DROP TABLE users`
- Subqueries with side effects (MySQL stored procedures)
**Mitigation**: Use a proper SQL parser or prevent semicolons entirely.
### Session Data Exposure
The `/hub/api/dev/session` endpoint exposes:
- Session ID
- User IP address
- User agent (truncated to 100 chars)
- Request method and URL
This is intentional for debugging but could be abused for session hijacking if credentials are compromised.
## Rate Limiting
All API endpoints have rate limits to prevent abuse:
| Endpoint | Limit | Rationale |
|----------|-------|-----------|
| Cache clear | 10/min | Prevent DoS via rapid cache invalidation |
| Log reading | 30/min | Limit log scraping |
| Route listing | 30/min | Prevent enumeration attacks |
| Session info | 60/min | Higher limit for debugging workflows |
Rate limits are per-user (authenticated) or per-IP (unauthenticated).
## SSH Connection Security
### Key Handling
The `testConnection()` method in `Servers.php` creates a temporary key file:
```php
$tempKeyPath = sys_get_temp_dir().'/ssh_test_'.uniqid();
file_put_contents($tempKeyPath, $server->getDecryptedPrivateKey());
chmod($tempKeyPath, 0600);
```
**Risk**: Predictable filename pattern and race condition window between write and use.
**Recommendation**: Use `tempnam()` for unique filename, write with restrictive umask.
### Connection Validation
- `StrictHostKeyChecking=no` is used for convenience but prevents MITM detection
- `BatchMode=yes` prevents interactive prompts
- `ConnectTimeout=10` limits hanging connections
### Workspace Isolation
The `RemoteServerManager::connect()` method validates workspace ownership before connecting:
```php
if (! $server->belongsToCurrentWorkspace()) {
throw new SshConnectionException('Unauthorised access to server.', $server->name);
}
```
This prevents cross-tenant server access.
## Route Testing Security
### Environment Restriction
Route testing is only available in `local` and `testing` environments:
```php
public function isTestingAllowed(): bool
{
return App::environment(['local', 'testing']);
}
```
This prevents accidental data modification in production.
### Destructive Operation Warnings
Routes using `DELETE`, `PUT`, `PATCH`, `POST` methods are marked as destructive and show warnings in the UI.
### CSRF Consideration
Test requests bypass CSRF as they are internal requests. The `X-Requested-With: XMLHttpRequest` header is set by default.
## Cookie Security
### Hades Cookie
The `SetHadesCookie` listener sets a cookie on login:
| Attribute | Value | Purpose |
|-----------|-------|---------|
| Value | Encrypted token | Validates Hades status |
| Duration | 1 year | Long-lived for convenience |
| HttpOnly | true | Prevents XSS access |
| Secure | true (production) | HTTPS only in production |
| SameSite | lax | CSRF protection |
### Icon Settings Cookie
`ApplyIconSettings` middleware reads `icon-style` and `icon-size` cookies set by JavaScript. These are stored in session for Blade component access.
**Risk**: Cookie values are user-controlled. Ensure they are properly escaped in views.
## Audit Logging
### Logged Actions
| Action | What's Logged |
|--------|---------------|
| Log clear | user_id, email, previous_size_bytes, IP |
| Database query | user_id, email, query, row_count, execution_time, IP |
| Blocked query | user_id, email, query (attempted), IP |
| Route test | user_id, route, method, IP |
| Server failure | Server ID, failure reason (via activity log) |
### Activity Log
Server model uses Spatie ActivityLog for tracking changes:
- Logged fields: name, ip, port, user, status
- Only dirty attributes logged
- Empty logs suppressed
## Third-Party Security
### Telescope
- Sensitive headers hidden: `cookie`, `x-csrf-token`, `x-xsrf-token`
- Sensitive parameters hidden: `_token`
- Gate restricts to Hades users (production) or all users (local)
### Horizon
- Gate restricts to Hades users
- Notifications configured via config (not hardcoded emails)
## Security Checklist for New Features
When adding new developer tools:
- [ ] Enforce Hades authorization in middleware AND component
- [ ] Add rate limiting for API endpoints
- [ ] Redact sensitive data in output
- [ ] Audit destructive operations
- [ ] Restrict environment (local/testing) for dangerous features
- [ ] Validate and sanitize all user input
- [ ] Use prepared statements for database queries
- [ ] Clean up temporary files/resources
- [ ] Document security considerations
## Incident Response
### If Hades credentials are compromised:
1. Revoke the user's Hades access
2. Rotate `HADES_TOKEN` environment variable
3. Review audit logs for suspicious activity
4. Check server access logs for SSH activity
5. Consider rotating SSH keys for connected servers
### If SSH key is exposed:
1. Delete the server record immediately
2. Regenerate SSH key on the actual server
3. Review server logs for unauthorized access
4. Update the server record with new key
## Recommendations for Production
1. **Separate Hades token per environment** - Don't use same token across staging/production
2. **Regular audit log review** - Monitor for unusual access patterns
3. **Limit Hades users** - Only grant to essential personnel
4. **Use hardware keys** - For servers, prefer hardware security modules
5. **Network segmentation** - Restrict admin panel to internal networks
6. **Two-factor authentication** - Require 2FA for Hades-tier accounts
7. **Session timeout** - Consider shorter session duration for Hades users

View file

@ -0,0 +1,100 @@
# AI Examples
## Workflow Example
Complete task management workflow:
```bash
# 1. List available tasks
core ai tasks --status pending
# 2. Auto-select and claim a task
core ai task --auto --claim
# 3. Work on the task...
# 4. Update progress
core ai task:update abc123 --progress 75
# 5. Commit with task reference
core ai task:commit abc123 -m 'implement feature'
# 6. Create PR
core ai task:pr abc123
# 7. Mark complete
core ai task:complete abc123 --output 'Feature implemented and PR created'
```
## Task Filtering
```bash
# By status
core ai tasks --status pending
core ai tasks --status in_progress
# By priority
core ai tasks --priority critical
core ai tasks --priority high
# By labels
core ai tasks --labels bug,urgent
# Combined filters
core ai tasks --status pending --priority high --labels bug
```
## Task Updates
```bash
# Change status
core ai task:update abc123 --status in_progress
core ai task:update abc123 --status blocked
# Update progress
core ai task:update abc123 --progress 25
core ai task:update abc123 --progress 50 --notes 'Halfway done'
core ai task:update abc123 --progress 100
```
## Git Integration
```bash
# Commit with task reference
core ai task:commit abc123 -m 'add authentication'
# With scope
core ai task:commit abc123 -m 'fix login' --scope auth
# Commit and push
core ai task:commit abc123 -m 'complete feature' --push
# Create PR
core ai task:pr abc123
# Draft PR
core ai task:pr abc123 --draft
# PR with labels
core ai task:pr abc123 --labels 'enhancement,ready-for-review'
# PR to different base
core ai task:pr abc123 --base develop
```
## Configuration
### Environment Variables
```env
AGENTIC_TOKEN=your-api-token
AGENTIC_BASE_URL=https://agentic.example.com
```
### ~/.core/agentic.yaml
```yaml
token: your-api-token
base_url: https://agentic.example.com
default_project: my-project
```

View file

@ -0,0 +1,262 @@
# core ai
AI agent task management and Claude Code integration.
## Task Management Commands
| Command | Description |
|---------|-------------|
| `tasks` | List available tasks from core-agentic |
| `task` | View task details or auto-select |
| `task:update` | Update task status or progress |
| `task:complete` | Mark task as completed or failed |
| `task:commit` | Create git commit with task reference |
| `task:pr` | Create GitHub PR linked to task |
## Claude Integration
| Command | Description |
|---------|-------------|
| `claude run` | Run Claude Code in current directory |
| `claude config` | Manage Claude configuration |
---
## Configuration
Task commands load configuration from:
1. Environment variables (`AGENTIC_TOKEN`, `AGENTIC_BASE_URL`)
2. `.env` file in current directory
3. `~/.core/agentic.yaml`
---
## ai tasks
List available tasks from core-agentic.
```bash
core ai tasks [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--status` | Filter by status (`pending`, `in_progress`, `completed`, `blocked`) |
| `--priority` | Filter by priority (`critical`, `high`, `medium`, `low`) |
| `--labels` | Filter by labels (comma-separated) |
| `--project` | Filter by project |
| `--limit` | Max number of tasks to return (default: 20) |
### Examples
```bash
# List all pending tasks
core ai tasks
# Filter by status and priority
core ai tasks --status pending --priority high
# Filter by labels
core ai tasks --labels bug,urgent
```
---
## ai task
View task details or auto-select a task.
```bash
core ai task [task-id] [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--auto` | Auto-select highest priority pending task |
| `--claim` | Claim the task after showing details |
| `--context` | Show gathered context for AI collaboration |
### Examples
```bash
# Show task details
core ai task abc123
# Show and claim
core ai task abc123 --claim
# Show with context
core ai task abc123 --context
# Auto-select highest priority pending task
core ai task --auto
```
---
## ai task:update
Update a task's status, progress, or notes.
```bash
core ai task:update <task-id> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--status` | New status (`pending`, `in_progress`, `completed`, `blocked`) |
| `--progress` | Progress percentage (0-100) |
| `--notes` | Notes about the update |
### Examples
```bash
# Set task to in progress
core ai task:update abc123 --status in_progress
# Update progress with notes
core ai task:update abc123 --progress 50 --notes 'Halfway done'
```
---
## ai task:complete
Mark a task as completed with optional output and artifacts.
```bash
core ai task:complete <task-id> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--output` | Summary of the completed work |
| `--failed` | Mark the task as failed |
| `--error` | Error message if failed |
### Examples
```bash
# Complete successfully
core ai task:complete abc123 --output 'Feature implemented'
# Mark as failed
core ai task:complete abc123 --failed --error 'Build failed'
```
---
## ai task:commit
Create a git commit with a task reference and co-author attribution.
```bash
core ai task:commit <task-id> [flags]
```
Commit message format:
```
feat(scope): description
Task: #123
Co-Authored-By: Claude <noreply@anthropic.com>
```
### Flags
| Flag | Description |
|------|-------------|
| `-m`, `--message` | Commit message (without task reference) |
| `--scope` | Scope for the commit type (e.g., `auth`, `api`, `ui`) |
| `--push` | Push changes after committing |
### Examples
```bash
# Commit with message
core ai task:commit abc123 --message 'add user authentication'
# With scope
core ai task:commit abc123 -m 'fix login bug' --scope auth
# Commit and push
core ai task:commit abc123 -m 'update docs' --push
```
---
## ai task:pr
Create a GitHub pull request linked to a task.
```bash
core ai task:pr <task-id> [flags]
```
Requires the GitHub CLI (`gh`) to be installed and authenticated.
### Flags
| Flag | Description |
|------|-------------|
| `--title` | PR title (defaults to task title) |
| `--base` | Base branch (defaults to main) |
| `--draft` | Create as draft PR |
| `--labels` | Labels to add (comma-separated) |
### Examples
```bash
# Create PR with defaults
core ai task:pr abc123
# Custom title
core ai task:pr abc123 --title 'Add authentication feature'
# Draft PR with labels
core ai task:pr abc123 --draft --labels 'enhancement,needs-review'
# Target different base branch
core ai task:pr abc123 --base develop
```
---
## ai claude
Claude Code integration commands.
### ai claude run
Run Claude Code in the current directory.
```bash
core ai claude run
```
### ai claude config
Manage Claude configuration.
```bash
core ai claude config
```
---
## Workflow Example
See [Workflow Example](example.md#workflow-example) for a complete task management workflow.
## See Also
- [dev](../dev/) - Multi-repo workflow commands
- [Claude Code documentation](https://claude.ai/code)

View file

@ -0,0 +1,83 @@
# Build Examples
## Quick Start
```bash
# Auto-detect and build
core build
# Build for specific platforms
core build --targets linux/amd64,darwin/arm64
# CI mode
core build --ci
```
## Configuration
`.core/build.yaml`:
```yaml
version: 1
project:
name: myapp
binary: myapp
build:
main: ./cmd/myapp
ldflags:
- -s -w
- -X main.version={{.Version}}
targets:
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: darwin
arch: arm64
```
## Cross-Platform Build
```bash
core build --targets linux/amd64,linux/arm64,darwin/arm64,windows/amd64
```
Output:
```
dist/
├── myapp-linux-amd64.tar.gz
├── myapp-linux-arm64.tar.gz
├── myapp-darwin-arm64.tar.gz
├── myapp-windows-amd64.zip
└── CHECKSUMS.txt
```
## Code Signing
```yaml
sign:
enabled: true
gpg:
key: $GPG_KEY_ID
macos:
identity: "Developer ID Application: Your Name (TEAM_ID)"
notarize: true
apple_id: $APPLE_ID
team_id: $APPLE_TEAM_ID
app_password: $APPLE_APP_PASSWORD
```
## Docker Build
```bash
core build --type docker --image ghcr.io/myorg/myapp
```
## Wails Desktop App
```bash
core build --type wails --targets darwin/arm64,windows/amd64
```

View file

@ -2,6 +2,14 @@
Build Go, Wails, Docker, and LinuxKit projects with automatic project detection.
## Subcommands
| Command | Description |
|---------|-------------|
| [sdk](sdk/) | Generate API SDKs from OpenAPI |
| `from-path` | Build from a local directory |
| `pwa` | Build from a live PWA URL |
## Usage
```bash
@ -12,12 +20,17 @@ core build [flags]
| Flag | Description |
|------|-------------|
| `--type` | Project type: `go`, `wails`, `docker`, `linuxkit` (auto-detected) |
| `--type` | Project type: `go`, `wails`, `docker`, `linuxkit`, `taskfile` (auto-detected) |
| `--targets` | Build targets: `linux/amd64,darwin/arm64,windows/amd64` |
| `--output` | Output directory (default: `dist`) |
| `--ci` | CI mode - non-interactive, fail fast |
| `--ci` | CI mode - minimal output with JSON artifact list at the end |
| `--image` | Docker image name (for docker builds) |
| `--no-sign` | Skip code signing |
| `--config` | Config file path (for linuxkit: YAML config, for docker: Dockerfile) |
| `--format` | Output format for linuxkit (iso-bios, qcow2-bios, raw, vmdk) |
| `--push` | Push Docker image after build (default: false) |
| `--archive` | Create archives (tar.gz for linux/darwin, zip for windows) - default: true |
| `--checksum` | Generate SHA256 checksums and CHECKSUMS.txt - default: true |
| `--no-sign` | Skip all code signing |
| `--notarize` | Enable macOS notarization (requires Apple credentials) |
## Examples
@ -53,6 +66,9 @@ core build --type docker
# With custom image name
core build --type docker --image ghcr.io/myorg/myapp
# Build and push to registry
core build --type docker --image ghcr.io/myorg/myapp --push
```
### LinuxKit Image
@ -60,6 +76,9 @@ core build --type docker --image ghcr.io/myorg/myapp
```bash
# Build LinuxKit ISO
core build --type linuxkit
# Build with specific format
core build --type linuxkit --config linuxkit.yml --format qcow2-bios
```
## Project Detection
@ -71,6 +90,7 @@ Core automatically detects project type based on files:
| `wails.json` | Wails |
| `go.mod` | Go |
| `Dockerfile` | Docker |
| `Taskfile.yml` | Taskfile |
| `composer.json` | PHP |
| `package.json` | Node |
@ -90,40 +110,7 @@ dist/
## Configuration
Optional `.core/build.yaml`:
```yaml
version: 1
project:
name: myapp
binary: myapp
build:
main: ./cmd/myapp
ldflags:
- -s -w
- -X main.version={{.Version}}
targets:
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: darwin
arch: arm64
sign:
enabled: true
gpg:
key: $GPG_KEY_ID
macos:
identity: "Developer ID Application: Your Name (TEAM_ID)"
notarize: false
apple_id: $APPLE_ID
team_id: $APPLE_TEAM_ID
app_password: $APPLE_APP_PASSWORD
```
Optional `.core/build.yaml` - see [Configuration](example.md#configuration) for examples.
## Code Signing
@ -169,3 +156,21 @@ core build --notarize
| `APPLE_ID` | Apple account email |
| `APPLE_TEAM_ID` | Apple Developer Team ID |
| `APPLE_APP_PASSWORD` | App-specific password for notarization |
## Building from PWAs and Static Sites
### Build from Local Directory
Build a desktop app from static web application files:
```bash
core build from-path --path ./dist
```
### Build from Live PWA
Build a desktop app from a live Progressive Web App URL:
```bash
core build pwa --url https://example.com
```

View file

@ -0,0 +1,56 @@
# SDK Build Examples
## Generate All SDKs
```bash
core build sdk
```
## Specific Language
```bash
core build sdk --lang typescript
core build sdk --lang php
core build sdk --lang go
```
## Custom Spec
```bash
core build sdk --spec ./api/openapi.yaml
```
## With Version
```bash
core build sdk --version v2.0.0
```
## Preview
```bash
core build sdk --dry-run
```
## Configuration
`.core/sdk.yaml`:
```yaml
version: 1
spec: ./api/openapi.yaml
languages:
- name: typescript
output: sdk/typescript
package: "@myorg/api-client"
- name: php
output: sdk/php
namespace: MyOrg\ApiClient
- name: go
output: sdk/go
module: github.com/myorg/api-client-go
```

View file

@ -0,0 +1,27 @@
# core build sdk
Generate typed API clients from OpenAPI specifications. Supports TypeScript, Python, Go, and PHP.
## Usage
```bash
core build sdk [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--spec` | Path to OpenAPI spec file |
| `--lang` | Generate only this language (typescript, python, go, php) |
| `--version` | Version to embed in generated SDKs |
| `--dry-run` | Show what would be generated without writing files |
## Examples
```bash
core build sdk # Generate all
core build sdk --lang typescript # TypeScript only
core build sdk --spec ./api.yaml # Custom spec
core build sdk --dry-run # Preview
```

View file

@ -0,0 +1,36 @@
# CI Changelog Examples
```bash
core ci changelog
```
## Output
```markdown
## v1.2.0
### Features
- Add user authentication (#123)
- Support dark mode (#124)
### Bug Fixes
- Fix memory leak in worker (#125)
### Performance
- Optimize database queries (#126)
```
## Configuration
`.core/release.yaml`:
```yaml
changelog:
include:
- feat
- fix
- perf
exclude:
- chore
- docs
```

View file

@ -0,0 +1,28 @@
# core ci changelog
Generate changelog from conventional commits.
## Usage
```bash
core ci changelog
```
## Output
Generates markdown changelog from git commits since last tag:
```markdown
## v1.2.0
### Features
- Add user authentication (#123)
- Support dark mode (#124)
### Bug Fixes
- Fix memory leak in worker (#125)
```
## Configuration
See [configuration.md](../../../configuration.md) for changelog configuration options.

View file

@ -0,0 +1,90 @@
# CI Examples
## Quick Start
```bash
# Build first
core build
# Preview release
core ci
# Publish
core ci --we-are-go-for-launch
```
## Configuration
`.core/release.yaml`:
```yaml
version: 1
project:
name: myapp
repository: host-uk/myapp
publishers:
- type: github
```
## Publisher Examples
### GitHub + Docker
```yaml
publishers:
- type: github
- type: docker
registry: ghcr.io
image: host-uk/myapp
platforms:
- linux/amd64
- linux/arm64
tags:
- latest
- "{{.Version}}"
```
### Full Stack (GitHub + npm + Homebrew)
```yaml
publishers:
- type: github
- type: npm
package: "@host-uk/myapp"
access: public
- type: homebrew
tap: host-uk/homebrew-tap
```
### LinuxKit Image
```yaml
publishers:
- type: linuxkit
config: .core/linuxkit/server.yml
formats:
- iso
- qcow2
platforms:
- linux/amd64
- linux/arm64
```
## Changelog Configuration
```yaml
changelog:
include:
- feat
- fix
- perf
exclude:
- chore
- docs
- test
```

View file

@ -0,0 +1,79 @@
# core ci
Publish releases to GitHub, Docker, npm, Homebrew, and more.
**Safety:** Dry-run by default. Use `--we-are-go-for-launch` to actually publish.
## Subcommands
| Command | Description |
|---------|-------------|
| [init](init/) | Initialize release config |
| [changelog](changelog/) | Generate changelog |
| [version](version/) | Show determined version |
## Usage
```bash
core ci [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--we-are-go-for-launch` | Actually publish (default is dry-run) |
| `--version` | Override version |
| `--draft` | Create as draft release |
| `--prerelease` | Mark as prerelease |
## Examples
```bash
# Preview what would be published (safe)
core ci
# Actually publish
core ci --we-are-go-for-launch
# Publish as draft
core ci --we-are-go-for-launch --draft
# Publish as prerelease
core ci --we-are-go-for-launch --prerelease
```
## Workflow
Build and publish are **separated** to prevent accidents:
```bash
# Step 1: Build artifacts
core build
core build sdk
# Step 2: Preview (dry-run by default)
core ci
# Step 3: Publish (explicit flag required)
core ci --we-are-go-for-launch
```
## Publishers
See [Publisher Examples](example.md#publisher-examples) for configuration.
| Type | Target |
|------|--------|
| `github` | GitHub Releases |
| `docker` | Container registries |
| `linuxkit` | LinuxKit images |
| `npm` | npm registry |
| `homebrew` | Homebrew tap |
| `scoop` | Scoop bucket |
| `aur` | Arch User Repository |
| `chocolatey` | Chocolatey |
## Changelog
Auto-generated from conventional commits. See [Changelog Configuration](example.md#changelog-configuration).

View file

@ -0,0 +1,17 @@
# CI Init Examples
```bash
core ci init
```
Creates `.core/release.yaml`:
```yaml
version: 1
project:
name: myapp
publishers:
- type: github
```

View file

@ -0,0 +1,11 @@
# core ci init
Initialize release configuration.
## Usage
```bash
core ci init
```
Creates `.core/release.yaml` with default configuration. See [Configuration](../example.md#configuration) for output format.

View file

@ -0,0 +1,18 @@
# CI Version Examples
```bash
core ci version
```
## Output
```
v1.2.0
```
## Version Resolution
1. `--version` flag (if provided)
2. Git tag on HEAD
3. Latest git tag + increment
4. `v0.0.1` (no tags)

View file

@ -0,0 +1,21 @@
# core ci version
Show the determined release version.
## Usage
```bash
core ci version
```
## Output
```
v1.2.0
```
Version is determined from:
1. `--version` flag (if provided)
2. Git tag on HEAD
3. Latest git tag + increment
4. `v0.0.1` (if no tags exist)

View file

@ -0,0 +1,61 @@
# core dev ci
Check CI status across all repositories.
Fetches GitHub Actions workflow status for all repos. Shows latest run status for each repo. Requires the `gh` CLI to be installed and authenticated.
## Usage
```bash
core dev ci [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--branch` | Filter by branch (default: main) |
| `--failed` | Show only failed runs |
## Examples
```bash
# Check CI status for all repos
core dev ci
# Check specific branch
core dev ci --branch develop
# Show only failures
core dev ci --failed
```
## Output
```
core-php ✓ passing 2m ago
core-tenant ✓ passing 5m ago
core-admin ✗ failed 12m ago
core-api ⏳ running now
core-bio ✓ passing 1h ago
```
## Status Icons
| Symbol | Meaning |
|--------|---------|
| `✓` | Passing |
| `✗` | Failed |
| `⏳` | Running |
| `-` | No runs |
## Requirements
- GitHub CLI (`gh`) must be installed
- Must be authenticated: `gh auth login`
## See Also
- [issues command](../issues/) - List open issues
- [reviews command](../reviews/) - List PRs needing review

View file

@ -0,0 +1,46 @@
# core dev commit
Claude-assisted commits across repositories.
Uses Claude to create commits for dirty repos. Shows uncommitted changes and invokes Claude to generate commit messages.
## Usage
```bash
core dev commit [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--all` | Commit all dirty repos without prompting |
## Examples
```bash
# Interactive commit (prompts for each repo)
core dev commit
# Commit all dirty repos automatically
core dev commit --all
# Use specific registry
core dev commit --registry ~/projects/repos.yaml
```
## How It Works
1. Scans all repositories for uncommitted changes
2. For each dirty repo:
- Shows the diff
- Invokes Claude to generate a commit message
- Creates the commit with `Co-Authored-By: Claude`
3. Reports success/failure for each repo
## See Also
- [health command](../health/) - Check repo status
- [push command](../push/) - Push commits after committing
- [work command](../work/) - Full workflow (status + commit + push)

View file

@ -0,0 +1,203 @@
# Dev Examples
## Multi-Repo Workflow
```bash
# Quick status
core dev health
# Detailed breakdown
core dev health --verbose
# Full workflow
core dev work
# Status only
core dev work --status
# Commit and push
core dev work --commit
# Commit dirty repos
core dev commit
# Commit all without prompting
core dev commit --all
# Push unpushed
core dev push
# Push without confirmation
core dev push --force
# Pull behind repos
core dev pull
# Pull all repos
core dev pull --all
```
## GitHub Integration
```bash
# Open issues
core dev issues
# Filter by assignee
core dev issues --assignee @me
# Limit results
core dev issues --limit 5
# PRs needing review
core dev reviews
# All PRs including drafts
core dev reviews --all
# Filter by author
core dev reviews --author username
# CI status
core dev ci
# Only failed runs
core dev ci --failed
# Specific branch
core dev ci --branch develop
```
## Dependency Analysis
```bash
# What depends on core-php?
core dev impact core-php
```
## Task Management
```bash
# List tasks
core ai tasks
# Filter by status and priority
core ai tasks --status pending --priority high
# Filter by labels
core ai tasks --labels bug,urgent
# Show task details
core ai task abc123
# Auto-select highest priority task
core ai task --auto
# Claim a task
core ai task abc123 --claim
# Update task status
core ai task:update abc123 --status in_progress
# Add progress notes
core ai task:update abc123 --progress 50 --notes 'Halfway done'
# Complete a task
core ai task:complete abc123 --output 'Feature implemented'
# Mark as failed
core ai task:complete abc123 --failed --error 'Build failed'
# Commit with task reference
core ai task:commit abc123 -m 'add user authentication'
# Commit with scope and push
core ai task:commit abc123 -m 'fix login bug' --scope auth --push
# Create PR for task
core ai task:pr abc123
# Create draft PR with labels
core ai task:pr abc123 --draft --labels 'enhancement,needs-review'
```
## Service API Management
```bash
# Synchronize public service APIs
core dev sync
# Or using the api command
core dev api sync
```
## Dev Environment
```bash
# First time setup
core dev install
core dev boot
# Open shell
core dev shell
# Mount and serve
core dev serve
# Run tests
core dev test
# Sandboxed Claude
core dev claude
```
## Configuration
### repos.yaml
```yaml
org: host-uk
repos:
core-php:
type: package
description: Foundation framework
core-tenant:
type: package
depends: [core-php]
```
### ~/.core/config.yaml
```yaml
version: 1
images:
source: auto # auto | github | registry | cdn
cdn:
url: https://images.example.com/core-devops
github:
repo: host-uk/core-images
registry:
image: ghcr.io/host-uk/core-devops
```
### .core/test.yaml
```yaml
version: 1
commands:
- name: unit
run: vendor/bin/pest --parallel
- name: types
run: vendor/bin/phpstan analyse
- name: lint
run: vendor/bin/pint --test
env:
APP_ENV: testing
DB_CONNECTION: sqlite
```

View file

@ -0,0 +1,52 @@
# core dev health
Quick health check across all repositories.
Shows a summary of repository health: total repos, dirty repos, unpushed commits, etc.
## Usage
```bash
core dev health [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--verbose` | Show detailed breakdown |
## Examples
```bash
# Quick health summary
core dev health
# Detailed breakdown
core dev health --verbose
# Use specific registry
core dev health --registry ~/projects/repos.yaml
```
## Output
```
18 repos │ 2 dirty │ 1 ahead │ all synced
```
With `--verbose`:
```
Repos: 18
Dirty: 2 (core-php, core-admin)
Ahead: 1 (core-tenant)
Behind: 0
Synced: ✓
```
## See Also
- [work command](../work/) - Full workflow (status + commit + push)
- [commit command](../commit/) - Claude-assisted commits

View file

@ -0,0 +1,65 @@
# core dev impact
Show impact of changing a repository.
Analyses the dependency graph to show which repos would be affected by changes to the specified repo.
## Usage
```bash
core dev impact <repo-name> [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
## Examples
```bash
# Show what depends on core-php
core dev impact core-php
# Show what depends on core-tenant
core dev impact core-tenant
```
## Output
```
Impact of changes to core-php:
Direct dependents (5):
core-tenant
core-admin
core-api
core-mcp
core-commerce
Indirect dependents (12):
core-bio (via core-tenant)
core-social (via core-tenant)
core-analytics (via core-tenant)
core-notify (via core-tenant)
core-trust (via core-tenant)
core-support (via core-tenant)
core-content (via core-tenant)
core-developer (via core-tenant)
core-agentic (via core-mcp)
...
Total: 17 repos affected
```
## Use Cases
- Before making breaking changes, see what needs updating
- Plan release order based on dependency graph
- Understand the ripple effect of changes
## See Also
- [health command](../health/) - Quick repo status
- [setup command](../../setup/) - Clone repos with dependencies

View file

@ -1,24 +1,55 @@
# core dev
Portable development environment with 100+ embedded tools.
Multi-repo workflow and portable development environment.
## Overview
Core DevOps provides a sandboxed, immutable development environment based on LinuxKit. It includes AI tools (Claude, Gemini), runtimes (Go, Node, PHP, Python, Rust), and infrastructure tools (Docker, Kubernetes, Terraform).
## Commands
## Multi-Repo Commands
| Command | Description |
|---------|-------------|
| `install` | Download the core-devops image for your platform |
| `boot` | Start the development environment |
| `stop` | Stop the running environment |
| `status` | Show environment status |
| `shell` | Open a shell in the environment |
| `serve` | Mount project and start dev server |
| `test` | Run tests inside the environment |
| `claude` | Start sandboxed Claude session |
| `update` | Update to latest image |
| [work](work/) | Full workflow: status + commit + push |
| `health` | Quick health check across repos |
| `commit` | Claude-assisted commits |
| `push` | Push repos with unpushed commits |
| `pull` | Pull repos that are behind |
| `issues` | List open issues |
| `reviews` | List PRs needing review |
| `ci` | Check CI status |
| `impact` | Show dependency impact |
| `api` | Tools for managing service APIs |
| `sync` | Synchronize public service APIs |
## Task Management Commands
> **Note:** Task management commands have moved to [`core ai`](../ai/).
| Command | Description |
|---------|-------------|
| [`ai tasks`](../ai/) | List available tasks from core-agentic |
| [`ai task`](../ai/) | Show task details or auto-select a task |
| [`ai task:update`](../ai/) | Update task status or progress |
| [`ai task:complete`](../ai/) | Mark a task as completed |
| [`ai task:commit`](../ai/) | Auto-commit changes with task reference |
| [`ai task:pr`](../ai/) | Create a pull request for a task |
## Dev Environment Commands
| Command | Description |
|---------|-------------|
| `install` | Download the core-devops image |
| `boot` | Start the environment |
| `stop` | Stop the environment |
| `status` | Show status |
| `shell` | Open shell |
| `serve` | Start dev server |
| `test` | Run tests |
| `claude` | Sandboxed Claude |
| `update` | Update image |
---
## Dev Environment Overview
Core DevOps provides a sandboxed, immutable development environment based on LinuxKit with 100+ embedded tools.
## Quick Start
@ -39,24 +70,16 @@ core dev serve
Download the core-devops image for your platform.
```bash
core dev install [flags]
core dev install
```
### Flags
| Flag | Description |
|------|-------------|
| `--source` | Image source: `github`, `registry`, `cdn` (default: auto) |
| `--force` | Force re-download even if exists |
Downloads the platform-specific dev environment image including Go, PHP, Node.js, Python, Docker, and Claude CLI. Downloads are cached at `~/.core/images/`.
### Examples
```bash
# Download image (auto-detects platform)
core dev install
# Force re-download
core dev install --force
```
## dev boot
@ -72,8 +95,8 @@ core dev boot [flags]
| Flag | Description |
|------|-------------|
| `--memory` | Memory allocation in MB (default: 4096) |
| `--cpus` | Number of CPUs (default: 4) |
| `--name` | Container name (default: core-dev) |
| `--cpus` | Number of CPUs (default: 2) |
| `--fresh` | Stop existing and start fresh |
### Examples
@ -82,7 +105,10 @@ core dev boot [flags]
core dev boot
# More resources
core dev boot --memory 8192 --cpus 8
core dev boot --memory 8192 --cpus 4
# Fresh start
core dev boot --fresh
```
## dev shell
@ -90,9 +116,11 @@ core dev boot --memory 8192 --cpus 8
Open a shell in the running environment.
```bash
core dev shell [flags]
core dev shell [flags] [-- command]
```
Uses SSH by default, or serial console with `--console`.
### Flags
| Flag | Description |
@ -107,6 +135,9 @@ core dev shell
# Serial console (for debugging)
core dev shell --console
# Run a command
core dev shell -- ls -la
```
## dev serve
@ -155,11 +186,11 @@ core dev test [flags] [-- custom command]
| Flag | Description |
|------|-------------|
| `--unit` | Run only unit tests |
| `--name` | Run named test command from `.core/test.yaml` |
### Test Detection
Core auto-detects the test framework:
Core auto-detects the test framework or uses `.core/test.yaml`:
1. `.core/test.yaml` - Custom config
2. `composer.json``composer test`
@ -174,29 +205,16 @@ Core auto-detects the test framework:
# Auto-detect and run tests
core dev test
# Run named test from config
core dev test --name integration
# Custom command
core dev test -- go test -v ./pkg/...
```
### Test Configuration
Create `.core/test.yaml` for custom test setup:
```yaml
version: 1
commands:
- name: unit
run: vendor/bin/pest --parallel
- name: types
run: vendor/bin/phpstan analyse
- name: lint
run: vendor/bin/pint --test
env:
APP_ENV: testing
DB_CONNECTION: sqlite
```
Create `.core/test.yaml` for custom test setup - see [Configuration](example.md#configuration) for examples.
## dev claude
@ -210,8 +228,9 @@ core dev claude [flags]
| Flag | Description |
|------|-------------|
| `--no-auth` | Clean session without host credentials |
| `--auth` | Selective auth forwarding (e.g., `gh,anthropic`) |
| `--model` | Model to use (`opus`, `sonnet`) |
| `--no-auth` | Don't forward any auth credentials |
| `--auth` | Selective auth forwarding (`gh`, `anthropic`, `ssh`, `git`) |
### What Gets Forwarded
@ -227,11 +246,14 @@ By default, these are forwarded to the sandbox:
# Full auth forwarding (default)
core dev claude
# Use Opus model
core dev claude --model opus
# Clean sandbox
core dev claude --no-auth
# Only GitHub auth
core dev claude --auth=gh
# Only GitHub and Anthropic auth
core dev claude --auth gh,anthropic
```
### Why Use This?
@ -258,7 +280,7 @@ Output includes:
## dev update
Check for and download newer images.
Check for and apply updates.
```bash
core dev update [flags]
@ -268,7 +290,17 @@ core dev update [flags]
| Flag | Description |
|------|-------------|
| `--force` | Force download even if up to date |
| `--apply` | Download and apply the update |
### Examples
```bash
# Check for updates
core dev update
# Apply available update
core dev update --apply
```
## Embedded Tools
@ -293,23 +325,7 @@ The core-devops image includes 100+ tools:
## Configuration
Global config in `~/.core/config.yaml`:
```yaml
version: 1
images:
source: auto # auto | github | registry | cdn
cdn:
url: https://images.example.com/core-devops
github:
repo: host-uk/core-images
registry:
image: ghcr.io/host-uk/core-devops
```
Global config in `~/.core/config.yaml` - see [Configuration](example.md#configuration) for examples.
## Image Storage
@ -323,3 +339,50 @@ Images are stored in `~/.core/images/`:
├── core-devops-linux-amd64.qcow2
└── manifest.json
```
## Multi-Repo Commands
See the [work](work/) page for detailed documentation on multi-repo commands.
### dev ci
Check GitHub Actions workflow status across all repos.
```bash
core dev ci [flags]
```
#### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--branch` | Filter by branch (default: main) |
| `--failed` | Show only failed runs |
Requires the `gh` CLI to be installed and authenticated.
### dev api
Tools for managing service APIs.
```bash
core dev api sync
```
Synchronizes the public service APIs with their internal implementations.
### dev sync
Alias for `core dev api sync`. Synchronizes the public service APIs with their internal implementations.
```bash
core dev sync
```
This command scans the `pkg` directory for services and ensures that the top-level public API for each service is in sync with its internal implementation. It automatically generates the necessary Go files with type aliases.
## See Also
- [work](work/) - Multi-repo workflow commands (`core dev work`, `core dev health`, etc.)
- [ai](../ai/) - Task management commands (`core ai tasks`, `core ai task`, etc.)

View file

@ -0,0 +1,57 @@
# core dev issues
List open issues across all repositories.
Fetches open issues from GitHub for all repos in the registry. Requires the `gh` CLI to be installed and authenticated.
## Usage
```bash
core dev issues [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--assignee` | Filter by assignee (use `@me` for yourself) |
| `--limit` | Max issues per repo (default 10) |
## Examples
```bash
# List all open issues
core dev issues
# Show issues assigned to you
core dev issues --assignee @me
# Limit to 5 issues per repo
core dev issues --limit 5
# Filter by specific assignee
core dev issues --assignee username
```
## Output
```
core-php (3 issues)
#42 Add retry logic to HTTP client bug
#38 Update documentation for v2 API docs
#35 Support custom serializers enhancement
core-tenant (1 issue)
#12 Workspace isolation bug bug, critical
```
## Requirements
- GitHub CLI (`gh`) must be installed
- Must be authenticated: `gh auth login`
## See Also
- [reviews command](../reviews/) - List PRs needing review
- [ci command](../ci/) - Check CI status

View file

@ -0,0 +1,47 @@
# core dev pull
Pull updates across all repositories.
Pulls updates for all repos. By default only pulls repos that are behind. Use `--all` to pull all repos.
## Usage
```bash
core dev pull [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--all` | Pull all repos, not just those behind |
## Examples
```bash
# Pull only repos that are behind
core dev pull
# Pull all repos
core dev pull --all
# Use specific registry
core dev pull --registry ~/projects/repos.yaml
```
## Output
```
Pulling 2 repo(s) that are behind:
✓ core-php (3 commits)
✓ core-tenant (1 commit)
Done: 2 pulled
```
## See Also
- [push command](../push/) - Push local commits
- [health command](../health/) - Check sync status
- [work command](../work/) - Full workflow

View file

@ -0,0 +1,52 @@
# core dev push
Push commits across all repositories.
Pushes unpushed commits for all repos. Shows repos with commits to push and confirms before pushing.
## Usage
```bash
core dev push [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--force` | Skip confirmation prompt |
## Examples
```bash
# Push with confirmation
core dev push
# Push without confirmation
core dev push --force
# Use specific registry
core dev push --registry ~/projects/repos.yaml
```
## Output
```
3 repo(s) with unpushed commits:
core-php: 2 commit(s)
core-admin: 1 commit(s)
core-tenant: 1 commit(s)
Push all? [y/N] y
✓ core-php
✓ core-admin
✓ core-tenant
```
## See Also
- [commit command](../commit/) - Create commits before pushing
- [pull command](../pull/) - Pull updates from remote
- [work command](../work/) - Full workflow (status + commit + push)

View file

@ -0,0 +1,61 @@
# core dev reviews
List PRs needing review across all repositories.
Fetches open PRs from GitHub for all repos in the registry. Shows review status (approved, changes requested, pending). Requires the `gh` CLI to be installed and authenticated.
## Usage
```bash
core dev reviews [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--all` | Show all PRs including drafts |
| `--author` | Filter by PR author |
## Examples
```bash
# List PRs needing review
core dev reviews
# Include draft PRs
core dev reviews --all
# Filter by author
core dev reviews --author username
```
## Output
```
core-php (2 PRs)
#45 feat: Add caching layer ✓ approved @alice
#43 fix: Memory leak in worker ⏳ pending @bob
core-admin (1 PR)
#28 refactor: Extract components ✗ changes @charlie
```
## Review Status
| Symbol | Meaning |
|--------|---------|
| `✓` | Approved |
| `⏳` | Pending review |
| `✗` | Changes requested |
## Requirements
- GitHub CLI (`gh`) must be installed
- Must be authenticated: `gh auth login`
## See Also
- [issues command](../issues/) - List open issues
- [ci command](../ci/) - Check CI status

View file

@ -0,0 +1,33 @@
# Dev Work Examples
```bash
# Full workflow: status → commit → push
core dev work
# Status only
core dev work --status
```
## Output
```
┌─────────────┬────────┬──────────┬─────────┐
│ Repo │ Branch │ Status │ Behind │
├─────────────┼────────┼──────────┼─────────┤
│ core-php │ main │ clean │ 0 │
│ core-tenant │ main │ 2 files │ 0 │
│ core-admin │ dev │ clean │ 3 │
└─────────────┴────────┴──────────┴─────────┘
```
## Registry
```yaml
repos:
- name: core
path: ./core
url: https://github.com/host-uk/core
- name: core-php
path: ./core-php
url: https://github.com/host-uk/core-php
```

View file

@ -0,0 +1,293 @@
# core dev work
Multi-repo git operations for managing the host-uk organization.
## Overview
The `core dev work` command and related subcommands help manage multiple repositories in the host-uk ecosystem simultaneously.
## Commands
| Command | Description |
|---------|-------------|
| `core dev work` | Full workflow: status + commit + push |
| `core dev work --status` | Status table only |
| `core dev work --commit` | Use Claude to commit dirty repos |
| `core dev health` | Quick health check across all repos |
| `core dev commit` | Claude-assisted commits across repos |
| `core dev push` | Push commits across all repos |
| `core dev pull` | Pull updates across all repos |
| `core dev issues` | List open issues across all repos |
| `core dev reviews` | List PRs needing review |
| `core dev ci` | Check CI status across all repos |
| `core dev impact` | Show impact of changing a repo |
## core dev work
Manage git status, commits, and pushes across multiple repositories.
```bash
core dev work [flags]
```
Reads `repos.yaml` to discover repositories and their relationships. Shows status, optionally commits with Claude, and pushes changes.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--status` | Show status only, don't push |
| `--commit` | Use Claude to commit dirty repos before pushing |
### Examples
```bash
# Full workflow
core dev work
# Status only
core dev work --status
# Commit and push
core dev work --commit
```
## core dev health
Quick health check showing summary of repository health across all repos.
```bash
core dev health [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--verbose` | Show detailed breakdown |
Output shows:
- Total repos
- Dirty repos
- Unpushed commits
- Repos behind remote
### Examples
```bash
# Quick summary
core dev health
# Detailed breakdown
core dev health --verbose
```
## core dev issues
List open issues across all repositories.
```bash
core dev issues [flags]
```
Fetches open issues from GitHub for all repos in the registry. Requires the `gh` CLI to be installed and authenticated.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--assignee` | Filter by assignee (use `@me` for yourself) |
| `--limit` | Max issues per repo (default: 10) |
### Examples
```bash
# List all open issues
core dev issues
# Filter by assignee
core dev issues --assignee @me
# Limit results
core dev issues --limit 5
```
## core dev reviews
List pull requests needing review across all repos.
```bash
core dev reviews [flags]
```
Fetches open PRs from GitHub for all repos in the registry. Shows review status (approved, changes requested, pending). Requires the `gh` CLI to be installed and authenticated.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--all` | Show all PRs including drafts |
| `--author` | Filter by PR author |
### Examples
```bash
# List PRs needing review
core dev reviews
# Show all PRs including drafts
core dev reviews --all
# Filter by author
core dev reviews --author username
```
## core dev commit
Create commits across repos with Claude assistance.
```bash
core dev commit [flags]
```
Uses Claude to create commits for dirty repos. Shows uncommitted changes and invokes Claude to generate commit messages.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--all` | Commit all dirty repos without prompting |
### Examples
```bash
# Commit with prompts
core dev commit
# Commit all automatically
core dev commit --all
```
## core dev push
Push commits across all repos.
```bash
core dev push [flags]
```
Pushes unpushed commits for all repos. Shows repos with commits to push and confirms before pushing.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--force` | Skip confirmation prompt |
### Examples
```bash
# Push with confirmation
core dev push
# Skip confirmation
core dev push --force
```
## core dev pull
Pull updates across all repos.
```bash
core dev pull [flags]
```
Pulls updates for all repos. By default only pulls repos that are behind. Use `--all` to pull all repos.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--all` | Pull all repos, not just those behind |
### Examples
```bash
# Pull repos that are behind
core dev pull
# Pull all repos
core dev pull --all
```
## core dev ci
Check GitHub Actions workflow status across all repos.
```bash
core dev ci [flags]
```
Fetches GitHub Actions workflow status for all repos. Shows latest run status for each repo. Requires the `gh` CLI to be installed and authenticated.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
| `--branch` | Filter by branch (default: main) |
| `--failed` | Show only failed runs |
### Examples
```bash
# Show CI status for all repos
core dev ci
# Show only failed runs
core dev ci --failed
# Check specific branch
core dev ci --branch develop
```
## core dev impact
Show the impact of changing a repository.
```bash
core dev impact <repo> [flags]
```
Analyzes the dependency graph to show which repos would be affected by changes to the specified repo.
### Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
### Examples
```bash
# Show impact of changing core-php
core dev impact core-php
```
## Registry
These commands use `repos.yaml` to know which repos to manage. See [repos.yaml](../../../configuration.md#reposyaml) for format.
Use `core setup` to clone all repos from the registry.
## See Also
- [setup command](../../setup/) - Clone repos from registry
- [search command](../../pkg/search/) - Find and install repos

View file

@ -0,0 +1,14 @@
# Docs Examples
## List
```bash
core docs list
```
## Sync
```bash
core docs sync
core docs sync --output ./docs
```

View file

@ -107,4 +107,4 @@ The synced docs are used to build https://core.help:
## See Also
- [Configuration](../configuration.md) - Project configuration
- [Configuration](../../configuration.md) - Project configuration

View file

@ -0,0 +1,20 @@
# Doctor Examples
```bash
core doctor
```
## Output
```
✓ go 1.25.0
✓ git 2.43.0
✓ gh 2.40.0
✓ docker 24.0.7
✓ task 3.30.0
✓ golangci-lint 1.55.0
✗ wails (not installed)
✓ php 8.3.0
✓ composer 2.6.0
✓ node 20.10.0
```

View file

@ -5,9 +5,15 @@ Check your development environment for required tools and configuration.
## Usage
```bash
core doctor
core doctor [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--verbose` | Show detailed version information |
## What It Checks
### Required Tools
@ -71,5 +77,5 @@ All checks passed!
## See Also
- [setup command](setup.md) - Clone repos from registry
- [dev install](dev.md) - Install development environment
- [setup command](../setup/) - Clone repos from registry
- [dev](../dev/) - Development environment

View file

@ -0,0 +1,18 @@
# Go Coverage Examples
```bash
# Summary
core go cov
# HTML report
core go cov --html
# Open in browser
core go cov --open
# Fail if below threshold
core go cov --threshold 80
# Specific package
core go cov --pkg ./pkg/release
```

View file

@ -0,0 +1,28 @@
# core go cov
Generate coverage report with thresholds.
## Usage
```bash
core go cov [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--pkg` | Package to test (default: `./...`) |
| `--html` | Generate HTML coverage report |
| `--open` | Generate and open HTML report in browser |
| `--threshold` | Minimum coverage percentage (exit 1 if below) |
## Examples
```bash
core go cov # Summary
core go cov --html # HTML report
core go cov --open # Open in browser
core go cov --threshold 80 # Fail if < 80%
core go cov --pkg ./pkg/release # Specific package
```

View file

@ -0,0 +1,89 @@
# Go Examples
## Testing
```bash
# Run all tests
core go test
# Specific package
core go test --pkg ./pkg/core
# Specific test
core go test --run TestHash
# With coverage
core go test --coverage
# Race detection
core go test --race
```
## Coverage
```bash
# Summary
core go cov
# HTML report
core go cov --html
# Open in browser
core go cov --open
# Fail if below threshold
core go cov --threshold 80
```
## Formatting
```bash
# Check
core go fmt
# Fix
core go fmt --fix
# Show diff
core go fmt --diff
```
## Linting
```bash
# Check
core go lint
# Auto-fix
core go lint --fix
```
## Installing
```bash
# Auto-detect cmd/
core go install
# Specific path
core go install ./cmd/myapp
# Pure Go (no CGO)
core go install --no-cgo
```
## Module Management
```bash
core go mod tidy
core go mod download
core go mod verify
core go mod graph
```
## Workspace
```bash
core go work sync
core go work init
core go work use ./pkg/mymodule
```

View file

@ -0,0 +1,12 @@
# Go Format Examples
```bash
# Check only
core go fmt
# Apply fixes
core go fmt --fix
# Show diff
core go fmt --diff
```

View file

@ -0,0 +1,25 @@
# core go fmt
Format Go code using goimports or gofmt.
## Usage
```bash
core go fmt [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--fix` | Fix formatting in place |
| `--diff` | Show diff of changes |
| `--check` | Check only, exit 1 if not formatted |
## Examples
```bash
core go fmt # Check formatting
core go fmt --fix # Fix formatting
core go fmt --diff # Show diff
```

View file

@ -0,0 +1,15 @@
# core go
Go development tools with enhanced output and environment setup.
## Subcommands
| Command | Description |
|---------|-------------|
| [test](test/) | Run tests with coverage |
| [cov](cov/) | Run tests with coverage report |
| [fmt](fmt/) | Format Go code |
| [lint](lint/) | Run golangci-lint |
| [install](install/) | Install Go binary |
| [mod](mod/) | Module management |
| [work](work/) | Workspace management |

View file

@ -0,0 +1,15 @@
# Go Install Examples
```bash
# Auto-detect cmd/
core go install
# Specific path
core go install ./cmd/myapp
# Pure Go (no CGO)
core go install --no-cgo
# Verbose
core go install -v
```

View file

@ -0,0 +1,25 @@
# core go install
Install Go binary with auto-detection.
## Usage
```bash
core go install [path] [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--no-cgo` | Disable CGO |
| `-v` | Verbose |
## Examples
```bash
core go install # Install current module
core go install ./cmd/core # Install specific path
core go install --no-cgo # Pure Go (no C dependencies)
core go install -v # Verbose output
```

View file

@ -0,0 +1,22 @@
# Go Lint Examples
```bash
# Check
core go lint
# Auto-fix
core go lint --fix
```
## Configuration
`.golangci.yml`:
```yaml
linters:
enable:
- gofmt
- govet
- errcheck
- staticcheck
```

View file

@ -0,0 +1,22 @@
# core go lint
Run golangci-lint.
## Usage
```bash
core go lint [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--fix` | Fix issues automatically |
## Examples
```bash
core go lint # Check
core go lint --fix # Auto-fix
```

View file

@ -0,0 +1,29 @@
# core go mod download
Download modules to local cache.
Wrapper around `go mod download`. Downloads all dependencies to the module cache.
## Usage
```bash
core go mod download
```
## What It Does
- Downloads all modules in go.mod to `$GOPATH/pkg/mod`
- Useful for pre-populating cache for offline builds
- Validates checksums against go.sum
## Examples
```bash
# Download all dependencies
core go mod download
```
## See Also
- [tidy](../tidy/) - Clean up go.mod
- [verify](../verify/) - Verify checksums

View file

@ -0,0 +1,15 @@
# Go Module Examples
```bash
# Tidy
core go mod tidy
# Download
core go mod download
# Verify
core go mod verify
# Graph
core go mod graph
```

View file

@ -0,0 +1,44 @@
# core go mod graph
Print module dependency graph.
Wrapper around `go mod graph`. Outputs the module dependency graph in text form.
## Usage
```bash
core go mod graph
```
## What It Does
- Prints module dependencies as pairs
- Each line shows: `module@version dependency@version`
- Useful for understanding dependency relationships
## Examples
```bash
# Print dependency graph
core go mod graph
# Find who depends on a specific module
core go mod graph | grep "some/module"
# Visualise with graphviz
core go mod graph | dot -Tpng -o deps.png
```
## Output
```
github.com/host-uk/core github.com/stretchr/testify@v1.11.1
github.com/stretchr/testify@v1.11.1 github.com/davecgh/go-spew@v1.1.2
github.com/stretchr/testify@v1.11.1 github.com/pmezard/go-difflib@v1.0.1
...
```
## See Also
- [tidy](../tidy/) - Clean up go.mod
- [dev impact](../../../dev/impact/) - Show repo dependency impact

View file

@ -0,0 +1,21 @@
# core go mod
Module management.
## Subcommands
| Command | Description |
|---------|-------------|
| `tidy` | Add missing and remove unused modules |
| `download` | Download modules to local cache |
| `verify` | Verify dependencies |
| `graph` | Print module dependency graph |
## Examples
```bash
core go mod tidy
core go mod download
core go mod verify
core go mod graph
```

View file

@ -0,0 +1,29 @@
# core go mod tidy
Add missing and remove unused modules.
Wrapper around `go mod tidy`. Ensures go.mod and go.sum are in sync with the source code.
## Usage
```bash
core go mod tidy
```
## What It Does
- Adds missing module requirements
- Removes unused module requirements
- Updates go.sum with checksums
## Examples
```bash
# Tidy the current module
core go mod tidy
```
## See Also
- [download](../download/) - Download modules
- [verify](../verify/) - Verify dependencies

View file

@ -0,0 +1,41 @@
# core go mod verify
Verify dependencies have not been modified.
Wrapper around `go mod verify`. Checks that dependencies in the module cache match their checksums in go.sum.
## Usage
```bash
core go mod verify
```
## What It Does
- Verifies each module in the cache
- Compares against go.sum checksums
- Reports any tampering or corruption
## Examples
```bash
# Verify all dependencies
core go mod verify
```
## Output
```
all modules verified
```
Or if verification fails:
```
github.com/example/pkg v1.2.3: dir has been modified
```
## See Also
- [download](../download/) - Download modules
- [tidy](../tidy/) - Clean up go.mod

View file

@ -0,0 +1,27 @@
# Go Test Examples
```bash
# All tests
core go test
# Specific package
core go test --pkg ./pkg/core
# Specific test
core go test --run TestHash
# With coverage
core go test --coverage
# Race detection
core go test --race
# Short tests only
core go test --short
# Verbose
core go test -v
# JSON output (CI)
core go test --json
```

View file

@ -0,0 +1,31 @@
# core go test
Run Go tests with coverage and filtered output.
## Usage
```bash
core go test [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--pkg` | Package to test (default: `./...`) |
| `--run` | Run only tests matching regexp |
| `--short` | Run only short tests |
| `--race` | Enable race detector |
| `--coverage` | Show detailed per-package coverage |
| `--json` | Output JSON results |
| `-v` | Verbose output |
## Examples
```bash
core go test # All tests
core go test --pkg ./pkg/core # Specific package
core go test --run TestHash # Specific test
core go test --coverage # With coverage
core go test --race # Race detection
```

View file

@ -0,0 +1,19 @@
# core go work
Go workspace management commands.
## Subcommands
| Command | Description |
|---------|-------------|
| `sync` | Sync go.work with modules |
| `init` | Initialize go.work |
| `use` | Add module to workspace |
## Examples
```bash
core go work sync # Sync workspace
core go work init # Initialize workspace
core go work use ./pkg/mymodule # Add module to workspace
```

View file

@ -0,0 +1,40 @@
# core go work init
Initialize a Go workspace.
Wrapper around `go work init`. Creates a new go.work file in the current directory.
## Usage
```bash
core go work init
```
## What It Does
- Creates a go.work file
- Automatically adds current module if go.mod exists
- Enables multi-module development
## Examples
```bash
# Initialize workspace
core go work init
# Then add more modules
core go work use ./pkg/mymodule
```
## Generated File
```go
go 1.25
use .
```
## See Also
- [use](../use/) - Add module to workspace
- [sync](../sync/) - Sync workspace

View file

@ -0,0 +1,35 @@
# core go work sync
Sync go.work with modules.
Wrapper around `go work sync`. Synchronises the workspace's build list back to the workspace modules.
## Usage
```bash
core go work sync
```
## What It Does
- Updates each module's go.mod to match the workspace build list
- Ensures all modules use compatible dependency versions
- Run after adding new modules or updating dependencies
## Examples
```bash
# Sync workspace
core go work sync
```
## When To Use
- After running `go get` to update a dependency
- After adding a new module with `core go work use`
- When modules have conflicting dependency versions
## See Also
- [init](../init/) - Initialize workspace
- [use](../use/) - Add module to workspace

View file

@ -0,0 +1,46 @@
# core go work use
Add module to workspace.
Wrapper around `go work use`. Adds one or more modules to the go.work file.
## Usage
```bash
core go work use [paths...]
```
## What It Does
- Adds specified module paths to go.work
- Auto-discovers modules if no paths given
- Enables developing multiple modules together
## Examples
```bash
# Add a specific module
core go work use ./pkg/mymodule
# Add multiple modules
core go work use ./pkg/one ./pkg/two
# Auto-discover and add all modules
core go work use
```
## Auto-Discovery
When called without arguments, scans for go.mod files and adds all found modules:
```bash
core go work use
# Added ./pkg/build
# Added ./pkg/repos
# Added ./cmd/core
```
## See Also
- [init](../init/) - Initialize workspace
- [sync](../sync/) - Sync workspace

View file

@ -0,0 +1,31 @@
# Core CLI
Unified interface for Go/PHP development, multi-repo management, and deployment.
## Commands
| Command | Description |
|---------|-------------|
| [ai](ai/) | AI agent task management and Claude integration |
| [go](go/) | Go development tools |
| [php](php/) | Laravel/PHP development tools |
| [build](build/) | Build projects |
| [ci](ci/) | Publish releases |
| [sdk](sdk/) | SDK validation and compatibility |
| [dev](dev/) | Multi-repo workflow + dev environment |
| [pkg](pkg/) | Package management |
| [vm](vm/) | LinuxKit VM management |
| [docs](docs/) | Documentation management |
| [setup](setup/) | Clone repos from registry |
| [doctor](doctor/) | Check environment |
| [test](test/) | Run Go tests with coverage |
## Installation
```bash
go install github.com/host-uk/core/cmd/core@latest
```
Verify: `core doctor`
See [Getting Started](../getting-started.md) for all installation options.

View file

@ -1,138 +0,0 @@
# core php
Laravel/PHP development environment with FrankenPHP, Vite, Horizon, Reverb, and Redis.
## Commands
| Command | Description |
|---------|-------------|
| `core php dev` | Start development environment |
| `core php test` | Run PHPUnit/Pest tests |
| `core php fmt` | Format with Laravel Pint |
| `core php analyse` | Static analysis with PHPStan |
| `core php build` | Build production container |
| `core php deploy` | Deploy to Coolify |
## Development Environment
```bash
# Start all services
core php dev
```
This starts:
- FrankenPHP/Octane (HTTP server)
- Vite dev server (frontend)
- Laravel Horizon (queues)
- Laravel Reverb (WebSockets)
- Redis
```bash
# View unified logs
core php logs
# Stop all services
core php stop
```
## Testing
```bash
# Run tests
core php test
# Parallel testing
core php test --parallel
# With coverage
core php test --coverage
```
## Code Quality
```bash
# Format code
core php fmt
# Static analysis
core php analyse
# Run both
core php fmt && core php analyse
```
## Building
```bash
# Build Docker container
core php build
# Build LinuxKit image
core php build --type linuxkit
# Run production locally
core php serve --production
```
## Deployment
```bash
# Deploy to Coolify
core php deploy
# Deploy to staging
core php deploy --staging
# Check deployment status
core php deploy:status
# Rollback
core php deploy:rollback
```
## Package Management
Link local packages for development:
```bash
# Link a local package
core php packages link ../my-package
# Update linked packages
core php packages update
# Unlink
core php packages unlink my-package
```
## SSL/HTTPS
Local SSL with mkcert:
```bash
# Auto-configured with core php dev
# Uses mkcert for trusted local certificates
```
## Configuration
Optional `.core/php.yaml`:
```yaml
version: 1
dev:
domain: myapp.test
ssl: true
services:
- frankenphp
- vite
- horizon
- reverb
- redis
deploy:
coolify:
server: https://coolify.example.com
project: my-project
```

View file

@ -0,0 +1,111 @@
# PHP Examples
## Development
```bash
# Start all services
core php dev
# With HTTPS
core php dev --https
# Skip services
core php dev --no-vite --no-horizon
```
## Testing
```bash
# Run all
core php test
# Parallel
core php test --parallel
# With coverage
core php test --coverage
# Filter
core php test --filter UserTest
```
## Code Quality
```bash
# Format
core php fmt --fix
# Static analysis
core php analyse --level 9
```
## Deployment
```bash
# Production
core php deploy
# Staging
core php deploy --staging
# Wait for completion
core php deploy --wait
# Check status
core php deploy:status
# Rollback
core php deploy:rollback
```
## Configuration
### .env
```env
COOLIFY_URL=https://coolify.example.com
COOLIFY_TOKEN=your-api-token
COOLIFY_APP_ID=production-app-id
COOLIFY_STAGING_APP_ID=staging-app-id
```
### .core/php.yaml
```yaml
version: 1
dev:
domain: myapp.test
ssl: true
services:
- frankenphp
- vite
- horizon
- reverb
- redis
deploy:
coolify:
server: https://coolify.example.com
project: my-project
```
## Package Linking
```bash
# Link local packages
core php packages link ../my-package
# Update linked
core php packages update
# Unlink
core php packages unlink my-package
```
## SSL Setup
```bash
core php ssl
core php ssl --domain myapp.test
```

View file

@ -0,0 +1,413 @@
# core php
Laravel/PHP development tools with FrankenPHP.
## Commands
### Development
| Command | Description |
|---------|-------------|
| [`dev`](#php-dev) | Start development environment |
| [`logs`](#php-logs) | View service logs |
| [`stop`](#php-stop) | Stop all services |
| [`status`](#php-status) | Show service status |
| [`ssl`](#php-ssl) | Setup SSL certificates with mkcert |
### Build & Production
| Command | Description |
|---------|-------------|
| [`build`](#php-build) | Build Docker or LinuxKit image |
| [`serve`](#php-serve) | Run production container |
| [`shell`](#php-shell) | Open shell in running container |
### Code Quality
| Command | Description |
|---------|-------------|
| [`test`](#php-test) | Run PHP tests (PHPUnit/Pest) |
| [`fmt`](#php-fmt) | Format code with Laravel Pint |
| [`analyse`](#php-analyse) | Run PHPStan static analysis |
### Package Management
| Command | Description |
|---------|-------------|
| [`packages link`](#php-packages-link) | Link local packages by path |
| [`packages unlink`](#php-packages-unlink) | Unlink packages by name |
| [`packages update`](#php-packages-update) | Update linked packages |
| [`packages list`](#php-packages-list) | List linked packages |
### Deployment (Coolify)
| Command | Description |
|---------|-------------|
| [`deploy`](#php-deploy) | Deploy to Coolify |
| [`deploy:status`](#php-deploystatus) | Show deployment status |
| [`deploy:rollback`](#php-deployrollback) | Rollback to previous deployment |
| [`deploy:list`](#php-deploylist) | List recent deployments |
---
## php dev
Start the Laravel development environment with all detected services.
```bash
core php dev [flags]
```
### Services Orchestrated
- **FrankenPHP/Octane** - HTTP server (port 8000, HTTPS on 443)
- **Vite** - Frontend dev server (port 5173)
- **Laravel Horizon** - Queue workers
- **Laravel Reverb** - WebSocket server (port 8080)
- **Redis** - Cache and queue backend (port 6379)
### Flags
| Flag | Description |
|------|-------------|
| `--no-vite` | Skip Vite dev server |
| `--no-horizon` | Skip Laravel Horizon |
| `--no-reverb` | Skip Laravel Reverb |
| `--no-redis` | Skip Redis server |
| `--https` | Enable HTTPS with mkcert |
| `--domain` | Domain for SSL certificate (default: from APP_URL) |
| `--port` | FrankenPHP port (default: 8000) |
### Examples
```bash
# Start all detected services
core php dev
# With HTTPS
core php dev --https
# Skip optional services
core php dev --no-horizon --no-reverb
```
---
## php logs
Stream unified logs from all running services.
```bash
core php logs [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--follow` | Follow log output |
| `--service` | Specific service (frankenphp, vite, horizon, reverb, redis) |
---
## php stop
Stop all running Laravel services.
```bash
core php stop
```
---
## php status
Show the status of all Laravel services and project configuration.
```bash
core php status
```
---
## php ssl
Setup local SSL certificates using mkcert.
```bash
core php ssl [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--domain` | Domain for certificate (default: from APP_URL or localhost) |
---
## php build
Build a production-ready container image.
```bash
core php build [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--type` | Build type: `docker` (default) or `linuxkit` |
| `--name` | Image name (default: project directory name) |
| `--tag` | Image tag (default: latest) |
| `--platform` | Target platform (e.g., linux/amd64, linux/arm64) |
| `--dockerfile` | Path to custom Dockerfile |
| `--output` | Output path for LinuxKit image |
| `--format` | LinuxKit format: qcow2 (default), iso, raw, vmdk |
| `--template` | LinuxKit template name (default: server-php) |
| `--no-cache` | Build without cache |
### Examples
```bash
# Build Docker image
core php build
# With custom name and tag
core php build --name myapp --tag v1.0
# Build LinuxKit image
core php build --type linuxkit
```
---
## php serve
Run a production container.
```bash
core php serve [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--name` | Docker image name (required) |
| `--tag` | Image tag (default: latest) |
| `--container` | Container name |
| `--port` | HTTP port (default: 80) |
| `--https-port` | HTTPS port (default: 443) |
| `-d` | Run in detached mode |
| `--env-file` | Path to environment file |
### Examples
```bash
core php serve --name myapp
core php serve --name myapp -d
core php serve --name myapp --port 8080
```
---
## php shell
Open an interactive shell in a running container.
```bash
core php shell <container-id>
```
---
## php test
Run PHP tests using PHPUnit or Pest.
```bash
core php test [flags]
```
Auto-detects Pest if `tests/Pest.php` exists.
### Flags
| Flag | Description |
|------|-------------|
| `--parallel` | Run tests in parallel |
| `--coverage` | Generate code coverage |
| `--filter` | Filter tests by name pattern |
| `--group` | Run only tests in specified group |
### Examples
```bash
core php test
core php test --parallel --coverage
core php test --filter UserTest
```
---
## php fmt
Format PHP code using Laravel Pint.
```bash
core php fmt [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--fix` | Auto-fix formatting issues |
| `--diff` | Show diff of changes |
---
## php analyse
Run PHPStan or Larastan static analysis.
```bash
core php analyse [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--level` | PHPStan analysis level (0-9) |
| `--memory` | Memory limit (e.g., 2G) |
---
## php packages link
Link local PHP packages for development.
```bash
core php packages link <path> [<path>...]
```
Adds path repositories to composer.json with symlink enabled.
---
## php packages unlink
Remove linked packages from composer.json.
```bash
core php packages unlink <name> [<name>...]
```
---
## php packages update
Update linked packages via Composer.
```bash
core php packages update [<name>...]
```
---
## php packages list
List all locally linked packages.
```bash
core php packages list
```
---
## php deploy
Deploy the PHP application to Coolify.
```bash
core php deploy [flags]
```
### Configuration
Requires environment variables in `.env`:
```
COOLIFY_URL=https://coolify.example.com
COOLIFY_TOKEN=your-api-token
COOLIFY_APP_ID=production-app-id
COOLIFY_STAGING_APP_ID=staging-app-id
```
### Flags
| Flag | Description |
|------|-------------|
| `--staging` | Deploy to staging environment |
| `--force` | Force deployment even if no changes detected |
| `--wait` | Wait for deployment to complete |
---
## php deploy:status
Show the status of a deployment.
```bash
core php deploy:status [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--staging` | Check staging environment |
| `--id` | Specific deployment ID |
---
## php deploy:rollback
Rollback to a previous deployment.
```bash
core php deploy:rollback [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--staging` | Rollback staging environment |
| `--id` | Specific deployment ID to rollback to |
| `--wait` | Wait for rollback to complete |
---
## php deploy:list
List recent deployments.
```bash
core php deploy:list [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--staging` | List staging deployments |
| `--limit` | Number of deployments (default: 10) |
---
## Configuration
Optional `.core/php.yaml` - see [Configuration](example.md#configuration) for examples.

View file

@ -0,0 +1,36 @@
# Package Examples
## Search
```bash
core pkg search core-
core pkg search api
core pkg search --org myorg
```
## Install
```bash
core pkg install core-api
core pkg install host-uk/core-api
```
## List
```bash
core pkg list
core pkg list --format json
```
## Update
```bash
core pkg update
core pkg update core-api
```
## Outdated
```bash
core pkg outdated
```

View file

@ -0,0 +1,144 @@
# core pkg
Package management for host-uk repositories.
## Usage
```bash
core pkg <command> [flags]
```
## Commands
| Command | Description |
|---------|-------------|
| [`search`](#pkg-search) | Search GitHub for packages |
| [`install`](#pkg-install) | Clone a package from GitHub |
| [`list`](#pkg-list) | List installed packages |
| [`update`](#pkg-update) | Update installed packages |
| [`outdated`](#pkg-outdated) | Check for outdated packages |
---
## pkg search
Search GitHub for host-uk packages.
```bash
core pkg search [flags]
```
Results are cached for 1 hour in `.core/cache/`.
### Flags
| Flag | Description |
|------|-------------|
| `--org` | GitHub organisation (default: host-uk) |
| `--pattern` | Repo name pattern (* for wildcard) |
| `--type` | Filter by type in name (mod, services, plug, website) |
| `--limit` | Max results (default: 50) |
| `--refresh` | Bypass cache and fetch fresh data |
### Examples
```bash
# List all repos in org
core pkg search
# Search for core-* repos
core pkg search --pattern 'core-*'
# Search different org
core pkg search --org mycompany
# Bypass cache
core pkg search --refresh
```
---
## pkg install
Clone a package from GitHub.
```bash
core pkg install <org/repo> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--dir` | Target directory (default: ./packages or current dir) |
| `--add` | Add to repos.yaml registry |
### Examples
```bash
# Clone to packages/
core pkg install host-uk/core-php
# Clone to custom directory
core pkg install host-uk/core-tenant --dir ./packages
# Clone and add to registry
core pkg install host-uk/core-admin --add
```
---
## pkg list
List installed packages from repos.yaml.
```bash
core pkg list
```
Shows installed status (✓) and description for each package.
---
## pkg update
Pull latest changes for installed packages.
```bash
core pkg update [<name>...] [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--all` | Update all packages |
### Examples
```bash
# Update specific package
core pkg update core-php
# Update all packages
core pkg update --all
```
---
## pkg outdated
Check which packages have unpulled commits.
```bash
core pkg outdated
```
Fetches from remote and shows packages that are behind.
---
## See Also
- [setup](../setup/) - Clone all repos from registry
- [dev work](../dev/work/) - Multi-repo workflow

View file

@ -0,0 +1,23 @@
# Package Search Examples
```bash
# Find all core-* packages
core pkg search core-
# Search term
core pkg search api
# Different org
core pkg search --org myorg query
```
## Output
```
┌──────────────┬─────────────────────────────┐
│ Package │ Description │
├──────────────┼─────────────────────────────┤
│ core-api │ REST API framework │
│ core-auth │ Authentication utilities │
└──────────────┴─────────────────────────────┘
```

View file

@ -0,0 +1,75 @@
# core pkg search
Search GitHub for repositories matching a pattern.
Uses `gh` CLI for authenticated search. Results are cached for 1 hour.
## Usage
```bash
core pkg search [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--pattern` | Repo name pattern (* for wildcard) |
| `--org` | GitHub organization (default: host-uk) |
| `--type` | Filter by type in name (mod, services, plug, website) |
| `--limit` | Max results (default: 50) |
| `--refresh` | Bypass cache and fetch fresh data |
## Examples
```bash
# List all host-uk repos
core pkg search
# Search for core-* repos
core pkg search --pattern "core-*"
# Search different org
core pkg search --org mycompany
# Filter by type
core pkg search --type services
# Bypass cache
core pkg search --refresh
# Combine filters
core pkg search --pattern "core-*" --type mod --limit 20
```
## Output
```
Found 5 repositories:
host-uk/core
Go CLI for the host-uk ecosystem
★ 42 Go Updated 2 hours ago
host-uk/core-php
PHP/Laravel packages for Core
★ 18 PHP Updated 1 day ago
host-uk/core-images
Docker and LinuxKit images
★ 8 Dockerfile Updated 3 days ago
```
## Authentication
Uses GitHub CLI (`gh`) authentication. Ensure you're logged in:
```bash
gh auth status
gh auth login # if not authenticated
```
## See Also
- [pkg install](../) - Clone a package from GitHub
- [setup command](../../setup/) - Clone all repos from registry

View file

@ -1,201 +0,0 @@
# core release
Build and publish releases to GitHub, npm, Homebrew, Scoop, AUR, Chocolatey, Docker, and LinuxKit.
## Usage
```bash
core release [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--dry-run` | Preview what would be published |
| `--version` | Override version (default: git tag) |
| `--target` | Release target: `sdk` for SDK-only release |
| `--draft` | Create release as draft |
| `--prerelease` | Mark release as prerelease |
## Quick Start
```bash
# Initialize release config
core release init
# Preview release
core release --dry-run
# Release
core release
# SDK-only release
core release --target sdk
```
## SDK Release
Generate SDKs without building binaries:
```bash
# Generate SDKs with version from git tag
core release --target sdk
# Explicit version
core release --target sdk --version v1.2.3
# Preview
core release --target sdk --dry-run
```
This will:
1. Determine version from git tags (or `--version` flag)
2. Run breaking change detection if configured
3. Generate SDKs for all configured languages
4. Output to `sdk/` directory
See [SDK commands](sdk.md) for more details.
## Publishers
### GitHub Releases
Uploads artifacts and changelog to GitHub Releases.
```yaml
publishers:
- type: github
prerelease: false
draft: false
```
### npm
Publishes binary wrapper that downloads correct platform binary.
```yaml
publishers:
- type: npm
package: "@myorg/myapp"
access: public
```
Requires `NPM_TOKEN` environment variable.
### Homebrew
Generates formula and commits to tap repository.
```yaml
publishers:
- type: homebrew
tap: myorg/homebrew-tap
formula: myapp # optional, defaults to project name
```
For official Homebrew PR:
```yaml
publishers:
- type: homebrew
tap: myorg/homebrew-tap
official:
enabled: true
output: dist/homebrew
```
### Scoop
Generates manifest and commits to bucket repository.
```yaml
publishers:
- type: scoop
bucket: myorg/scoop-bucket
```
### AUR
Generates PKGBUILD and pushes to AUR.
```yaml
publishers:
- type: aur
maintainer: "Your Name <email@example.com>"
```
### Chocolatey
Generates NuSpec and optionally pushes to Chocolatey.
```yaml
publishers:
- type: chocolatey
push: false # generate only
```
Set `push: true` and `CHOCOLATEY_API_KEY` to publish.
### Docker
Builds and pushes multi-arch Docker images.
```yaml
publishers:
- type: docker
registry: ghcr.io
image: myorg/myapp
platforms:
- linux/amd64
- linux/arm64
tags:
- latest
- "{{.Version}}"
```
### LinuxKit
Builds immutable LinuxKit images.
```yaml
publishers:
- type: linuxkit
config: .core/linuxkit/server.yml
formats:
- iso
- qcow2
- docker # Immutable container
platforms:
- linux/amd64
- linux/arm64
```
## Full Example
See [examples/full-release.yaml](examples/full-release.yaml) for a complete configuration.
## Changelog
Changelog is auto-generated from conventional commits:
```
feat: Add new feature → Features
fix: Fix bug → Bug Fixes
perf: Improve performance → Performance
refactor: Refactor code → Refactoring
```
Configure in `.core/release.yaml`:
```yaml
changelog:
include:
- feat
- fix
- perf
exclude:
- chore
- docs
- test
```

View file

@ -1,132 +0,0 @@
# core run
Run LinuxKit images with qemu or hyperkit.
## Usage
```bash
core run <image> [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `-d, --detach` | Run in background |
| `--cpus` | Number of CPUs (default: 1) |
| `--mem` | Memory in MB (default: 1024) |
| `--disk` | Disk size (default: none) |
| `--template` | Use built-in template |
## Examples
### Run ISO Image
```bash
# Run LinuxKit ISO
core run server.iso
# With more resources
core run server.iso --cpus 2 --mem 2048
# Detached mode
core run server.iso -d
```
### Run from Template
```bash
# List available templates
core templates
# Run template
core run --template core-dev
```
### Formats
Supported image formats:
- `.iso` - Bootable ISO
- `.qcow2` - QEMU disk image
- `.raw` - Raw disk image
- `.vmdk` - VMware disk
## Container Management
```bash
# List running containers
core ps
# View logs
core logs <id>
# Follow logs
core logs -f <id>
# Execute command
core exec <id> <command>
# Stop container
core stop <id>
```
## Templates
Built-in templates in `.core/linuxkit/`:
| Template | Description |
|----------|-------------|
| `core-dev` | Development environment |
| `server-php` | FrankenPHP server |
### Custom Templates
Create `.core/linuxkit/mytemplate.yml`:
```yaml
kernel:
image: linuxkit/kernel:6.6
cmdline: "console=tty0"
init:
- linuxkit/init:latest
- linuxkit/runc:latest
- linuxkit/containerd:latest
services:
- name: myservice
image: myorg/myservice:latest
files:
- path: /etc/myconfig
contents: |
key: value
```
Then run:
```bash
core run --template mytemplate
```
## Networking
LinuxKit VMs get their own network namespace. Port forwarding:
```bash
# Forward port 8080
core run server.iso -p 8080:80
# Multiple ports
core run server.iso -p 8080:80 -p 8443:443
```
## Disk Persistence
```bash
# Create persistent disk
core run server.iso --disk 10G
# Attach existing disk
core run server.iso --disk /path/to/disk.qcow2
```

View file

@ -1,188 +0,0 @@
# core sdk
Generate typed API clients from OpenAPI specifications.
## Usage
```bash
core sdk <command> [flags]
```
## Commands
| Command | Description |
|---------|-------------|
| `generate` | Generate SDKs from OpenAPI spec |
| `validate` | Validate OpenAPI spec |
| `diff` | Check for breaking API changes |
## sdk generate
Generate typed API clients for multiple languages.
```bash
core sdk generate [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--spec` | Path to OpenAPI spec file (auto-detected) |
| `--lang` | Generate only this language |
### Examples
```bash
# Generate all configured SDKs
core sdk generate
# Generate only TypeScript SDK
core sdk generate --lang typescript
# Use specific spec file
core sdk generate --spec api/openapi.yaml
```
### Supported Languages
| Language | Generator |
|----------|-----------|
| TypeScript | openapi-generator (typescript-fetch) |
| Python | openapi-generator (python) |
| Go | openapi-generator (go) |
| PHP | openapi-generator (php) |
## sdk validate
Validate an OpenAPI specification file.
```bash
core sdk validate [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--spec` | Path to OpenAPI spec file (auto-detected) |
### Examples
```bash
# Validate detected spec
core sdk validate
# Validate specific file
core sdk validate --spec api/openapi.yaml
```
## sdk diff
Check for breaking changes between API versions.
```bash
core sdk diff [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--base` | Base spec version (git tag or file path) |
| `--spec` | Current spec file (auto-detected) |
### Examples
```bash
# Compare against previous release
core sdk diff --base v1.0.0
# Compare two files
core sdk diff --base old-api.yaml --spec new-api.yaml
```
### Breaking Changes Detected
- Removed endpoints
- Changed parameter types
- Removed required fields
- Changed response types
## Release Integration
Generate SDKs as part of the release process:
```bash
# Generate SDKs for release
core release --target sdk
# With explicit version
core release --target sdk --version v1.2.3
# Preview what would be generated
core release --target sdk --dry-run
```
See [release command](release.md) for full details.
## Configuration
Configure SDK generation in `.core/release.yaml`:
```yaml
sdk:
# OpenAPI spec path (auto-detected if not set)
spec: api/openapi.yaml
# Languages to generate
languages:
- typescript
- python
- go
- php
# Output directory
output: sdk
# Package naming
package:
name: my-api-sdk
# Breaking change detection
diff:
enabled: true
fail_on_breaking: false # Warn but continue
```
## Spec Auto-Detection
Core looks for OpenAPI specs in this order:
1. Path specified in config (`sdk.spec`)
2. `openapi.yaml` / `openapi.json`
3. `api/openapi.yaml` / `api/openapi.json`
4. `docs/openapi.yaml` / `docs/openapi.json`
5. Laravel Scramble endpoint (`/docs/api.json`)
## Output Structure
Generated SDKs are placed in language-specific directories:
```
sdk/
├── typescript/
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── python/
│ ├── my_api_sdk/
│ ├── setup.py
│ └── requirements.txt
├── go/
│ ├── client.go
│ └── go.mod
└── php/
├── src/
└── composer.json
```

View file

@ -0,0 +1,35 @@
# SDK Examples
## Validate
```bash
core sdk validate
core sdk validate --spec ./api.yaml
```
## Diff
```bash
# Compare with tag
core sdk diff --base v1.0.0
# Compare files
core sdk diff --base ./old-api.yaml --spec ./new-api.yaml
```
## Output
```
Breaking changes detected:
- DELETE /users/{id}/profile
Endpoint removed
- PATCH /users/{id}
Required field 'email' added
Non-breaking changes:
+ POST /users/{id}/avatar
New endpoint added
```

View file

@ -0,0 +1,106 @@
# core sdk
SDK validation and API compatibility tools.
To generate SDKs, use: `core build sdk`
## Usage
```bash
core sdk <command> [flags]
```
## Commands
| Command | Description |
|---------|-------------|
| `diff` | Check for breaking API changes |
| `validate` | Validate OpenAPI spec |
## sdk validate
Validate an OpenAPI specification file.
```bash
core sdk validate [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--spec` | Path to OpenAPI spec file (auto-detected) |
### Examples
```bash
# Validate detected spec
core sdk validate
# Validate specific file
core sdk validate --spec api/openapi.yaml
```
## sdk diff
Check for breaking changes between API versions.
```bash
core sdk diff [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--base` | Base spec version (git tag or file path) |
| `--spec` | Current spec file (auto-detected) |
### Examples
```bash
# Compare against previous release
core sdk diff --base v1.0.0
# Compare two files
core sdk diff --base old-api.yaml --spec new-api.yaml
```
### Breaking Changes Detected
- Removed endpoints
- Changed parameter types
- Removed required fields
- Changed response types
## SDK Generation
SDK generation is handled by `core build sdk`, not this command.
```bash
# Generate SDKs
core build sdk
# Generate specific language
core build sdk --lang typescript
# Preview without writing
core build sdk --dry-run
```
See [build sdk](../build/sdk/) for generation details.
## Spec Auto-Detection
Core looks for OpenAPI specs in this order:
1. Path specified in config (`sdk.spec`)
2. `openapi.yaml` / `openapi.json`
3. `api/openapi.yaml` / `api/openapi.json`
4. `docs/openapi.yaml` / `docs/openapi.json`
5. Laravel Scramble endpoint (`/docs/api.json`)
## See Also
- [build sdk](../build/sdk/) - Generate SDKs from OpenAPI
- [ci command](../ci/) - Release workflow

View file

@ -1,112 +0,0 @@
# core search & install
Search GitHub for repositories and install them locally.
## core search
Search GitHub for repositories matching a pattern.
```bash
core search <pattern> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--org` | Search within a specific organization |
| `--limit` | Maximum results (default: 10) |
| `--language` | Filter by programming language |
### Examples
```bash
# Search by pattern
core search "cli tool"
# Search within organization
core search --org host-uk
# Search with language filter
core search --org host-uk --language go
# Search all core-* repos
core search "core-" --org host-uk
```
### Output
```
Found 5 repositories:
host-uk/core
Go CLI for the host-uk ecosystem
★ 42 Go Updated 2 hours ago
host-uk/core-php
PHP/Laravel packages for Core
★ 18 PHP Updated 1 day ago
host-uk/core-images
Docker and LinuxKit images
★ 8 Dockerfile Updated 3 days ago
```
## core install
Clone a repository from GitHub.
```bash
core install <repo> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--path` | Destination directory (default: current dir) |
| `--branch` | Clone specific branch |
| `--depth` | Shallow clone depth |
### Examples
```bash
# Install by full name
core install host-uk/core
# Install to specific path
core install host-uk/core --path ~/Code/host-uk
# Install specific branch
core install host-uk/core --branch dev
# Shallow clone
core install host-uk/core --depth 1
```
### Authentication
Uses GitHub CLI (`gh`) authentication. Ensure you're logged in:
```bash
gh auth status
gh auth login # if not authenticated
```
## Workflow Example
```bash
# Find repositories
core search --org host-uk
# Install one
core install host-uk/core-php --path ~/Code/host-uk
# Check setup
core doctor
```
## See Also
- [setup command](setup.md) - Clone all repos from registry
- [doctor command](doctor.md) - Check environment

View file

@ -1,94 +0,0 @@
# core setup
Clone all repositories from the registry.
## Usage
```bash
core setup [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml |
| `--path` | Base directory for cloning (default: current dir) |
| `--ssh` | Use SSH URLs instead of HTTPS |
## Examples
```bash
# Clone all repos from registry
core setup
# Clone to specific directory
core setup --path ~/Code/host-uk
# Use SSH for cloning
core setup --ssh
```
## Registry Format
The registry file (`repos.yaml`) defines repositories:
```yaml
repos:
- name: core
url: https://github.com/host-uk/core
description: Go CLI for the host-uk ecosystem
- name: core-php
url: https://github.com/host-uk/core-php
description: PHP/Laravel packages
- name: core-images
url: https://github.com/host-uk/core-images
description: Docker and LinuxKit images
- name: core-api
url: https://github.com/host-uk/core-api
description: API service
```
## Output
```
Setting up host-uk workspace...
Cloning repositories:
[1/4] core............... ✓
[2/4] core-php........... ✓
[3/4] core-images........ ✓
[4/4] core-api........... ✓
Done! 4 repositories cloned to ~/Code/host-uk
```
## Finding Registry
Core looks for `repos.yaml` in:
1. Current directory
2. Parent directories (up to 5 levels)
3. `~/.core/repos.yaml`
## After Setup
```bash
# Check health of all repos
core health
# Pull latest changes
core pull --all
# Check CI status
core ci
```
## See Also
- [work commands](work.md) - Multi-repo operations
- [search command](search.md) - Find repos on GitHub
- [install command](search.md) - Clone individual repos

View file

@ -0,0 +1,293 @@
# Setup Examples
## Clone from Registry
```bash
# Clone all repos defined in repos.yaml
core setup
# Preview what would be cloned
core setup --dry-run
# Only foundation packages
core setup --only foundation
# Multiple types
core setup --only foundation,module
# Use specific registry file
core setup --registry ~/projects/repos.yaml
```
## Bootstrap New Workspace
```bash
# In an empty directory - bootstraps in place
mkdir my-workspace && cd my-workspace
core setup
# Shows interactive wizard to select packages:
# ┌─────────────────────────────────────────────┐
# │ Select packages to clone │
# │ Use space to select, enter to confirm │
# │ │
# │ ── Foundation (core framework) ── │
# │ ☑ core-php Foundation framework │
# │ ☑ core-tenant Multi-tenancy module │
# │ │
# │ ── Products (applications) ── │
# │ ☐ core-bio Link-in-bio product │
# │ ☐ core-social Social scheduling │
# └─────────────────────────────────────────────┘
# Non-interactive: clone all packages
core setup --all
# Create workspace in subdirectory
cd ~/Code
core setup --name my-project
# CI mode: fully non-interactive
core setup --all --name ci-test
```
## Setup Single Repository
```bash
# In a git repo without .core/ configuration
cd ~/Code/my-go-project
core setup
# Shows choice dialog:
# ┌─────────────────────────────────────────────┐
# │ Setup options │
# │ You're in a git repository. What would you │
# │ like to do? │
# │ │
# │ ● Setup this repo (create .core/ config) │
# │ ○ Create a new workspace (clone repos) │
# └─────────────────────────────────────────────┘
# Preview generated configuration
core setup --dry-run
# Output:
# → Setting up repository configuration
#
# ✓ Detected project type: go
# → Also found: (none)
#
# → Would create:
# /Users/you/Code/my-go-project/.core/build.yaml
#
# Configuration preview:
# version: 1
# project:
# name: my-go-project
# description: Go application
# main: ./cmd/my-go-project
# binary: my-go-project
# ...
```
## Configuration Files
### repos.yaml (Workspace Registry)
```yaml
org: host-uk
base_path: .
defaults:
ci: github
license: EUPL-1.2
branch: main
repos:
core-php:
type: foundation
description: Foundation framework
core-tenant:
type: module
depends_on: [core-php]
description: Multi-tenancy module
core-admin:
type: module
depends_on: [core-php, core-tenant]
description: Admin panel
core-bio:
type: product
depends_on: [core-php, core-tenant]
description: Link-in-bio product
domain: bio.host.uk.com
core-devops:
type: foundation
clone: false # Already exists, skip cloning
```
### .core/build.yaml (Repository Config)
Generated for Go projects:
```yaml
version: 1
project:
name: my-project
description: Go application
main: ./cmd/my-project
binary: my-project
build:
cgo: false
flags:
- -trimpath
ldflags:
- -s
- -w
env: []
targets:
- os: linux
arch: amd64
- os: linux
arch: arm64
- os: darwin
arch: amd64
- os: darwin
arch: arm64
- os: windows
arch: amd64
sign:
enabled: false
```
Generated for Wails projects:
```yaml
version: 1
project:
name: my-app
description: Wails desktop application
main: .
binary: my-app
targets:
- os: darwin
arch: amd64
- os: darwin
arch: arm64
- os: windows
arch: amd64
- os: linux
arch: amd64
```
### .core/release.yaml (Release Config)
Generated for Go projects:
```yaml
version: 1
project:
name: my-project
repository: owner/my-project
changelog:
include:
- feat
- fix
- perf
- refactor
exclude:
- chore
- docs
- style
- test
publishers:
- type: github
draft: false
prerelease: false
```
### .core/test.yaml (Test Config)
Generated for Go projects:
```yaml
version: 1
commands:
- name: unit
run: go test ./...
- name: coverage
run: go test -coverprofile=coverage.out ./...
- name: race
run: go test -race ./...
env:
CGO_ENABLED: "0"
```
Generated for PHP projects:
```yaml
version: 1
commands:
- name: unit
run: vendor/bin/pest --parallel
- name: types
run: vendor/bin/phpstan analyse
- name: lint
run: vendor/bin/pint --test
env:
APP_ENV: testing
DB_CONNECTION: sqlite
```
Generated for Node.js projects:
```yaml
version: 1
commands:
- name: unit
run: npm test
- name: lint
run: npm run lint
- name: typecheck
run: npm run typecheck
env:
NODE_ENV: test
```
## Workflow Examples
### New Developer Setup
```bash
# Clone the workspace
mkdir host-uk && cd host-uk
core setup
# Select packages in wizard, then:
core health # Check all repos are healthy
core doctor # Verify environment
```
### CI Pipeline Setup
```bash
# Non-interactive full clone
core setup --all --name workspace
# Or with specific packages
core setup --only foundation,module --name workspace
```
### Adding Build Config to Existing Repo
```bash
cd my-existing-project
core setup # Choose "Setup this repo"
# Edit .core/build.yaml as needed
core build # Build the project
```

View file

@ -0,0 +1,213 @@
# core setup
Clone repositories from registry or bootstrap a new workspace.
## Overview
The `setup` command operates in three modes:
1. **Registry mode** - When `repos.yaml` exists nearby, clones repositories into packages/
2. **Bootstrap mode** - When no registry exists, clones `core-devops` first, then presents an interactive wizard to select packages
3. **Repo setup mode** - When run in a git repo root, offers to create `.core/build.yaml` configuration
## Usage
```bash
core setup [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--registry` | Path to repos.yaml (auto-detected if not specified) |
| `--dry-run` | Show what would be cloned without cloning |
| `--only` | Only clone repos of these types (comma-separated: foundation,module,product) |
| `--all` | Skip wizard, clone all packages (non-interactive) |
| `--name` | Project directory name for bootstrap mode |
| `--build` | Run build after cloning |
---
## Registry Mode
When `repos.yaml` is found nearby (current directory or parents), setup clones all defined repositories:
```bash
# In a directory with repos.yaml
core setup
# Preview what would be cloned
core setup --dry-run
# Only clone foundation packages
core setup --only foundation
# Multiple types
core setup --only foundation,module
```
In registry mode with a TTY, an interactive wizard allows you to select which packages to clone. Use `--all` to skip the wizard and clone everything.
---
## Bootstrap Mode
When no `repos.yaml` exists, setup enters bootstrap mode:
```bash
# In an empty directory - bootstraps workspace in place
mkdir my-project && cd my-project
core setup
# In a non-empty directory - creates subdirectory
cd ~/Code
core setup --name my-workspace
# Non-interactive: clone all packages
core setup --all --name ci-test
```
Bootstrap mode:
1. Detects if current directory is empty
2. If not empty, prompts for project name (or uses `--name`)
3. Clones `core-devops` (contains `repos.yaml`)
4. Loads the registry from core-devops
5. Shows interactive package selection wizard (unless `--all`)
6. Clones selected packages
7. Optionally runs build (with `--build`)
---
## Repo Setup Mode
When run in a git repository root (without `repos.yaml`), setup offers two choices:
1. **Setup Working Directory** - Creates `.core/build.yaml` based on detected project type
2. **Create Package** - Creates a subdirectory and clones packages there
```bash
cd ~/Code/my-go-project
core setup
# Output:
# >> This directory is a git repository
# > Setup Working Directory
# Create Package (clone repos into subdirectory)
```
Choosing "Setup Working Directory" detects the project type and generates configuration:
| Detected File | Project Type |
|---------------|--------------|
| `wails.json` | Wails |
| `go.mod` | Go |
| `composer.json` | PHP |
| `package.json` | Node.js |
Creates three config files in `.core/`:
| File | Purpose |
|------|---------|
| `build.yaml` | Build targets, flags, output settings |
| `release.yaml` | Changelog format, GitHub release config |
| `test.yaml` | Test commands, environment variables |
Also auto-detects GitHub repo from git remote for release config.
See [Configuration Files](example.md#configuration-files) for generated config examples.
---
## Interactive Wizard
When running in a terminal (TTY), the setup command presents an interactive multi-select wizard:
- Packages are grouped by type (foundation, module, product, template)
- Use arrow keys to navigate
- Press space to select/deselect packages
- Type to filter the list
- Press enter to confirm selection
The wizard is skipped when:
- `--all` flag is specified
- Not running in a TTY (e.g., CI pipelines)
- `--dry-run` is specified
---
## Examples
### Clone from Registry
```bash
# Clone all repos (interactive wizard)
core setup
# Clone all repos (non-interactive)
core setup --all
# Preview without cloning
core setup --dry-run
# Only foundation packages
core setup --only foundation
```
### Bootstrap New Workspace
```bash
# Interactive bootstrap in empty directory
mkdir workspace && cd workspace
core setup
# Non-interactive with all packages
core setup --all --name my-project
# Bootstrap and run build
core setup --all --name my-project --build
```
---
## Registry Format
The registry file (`repos.yaml`) defines repositories. See [Configuration Files](example.md#configuration-files) for format.
---
## Finding Registry
Core looks for `repos.yaml` in:
1. Current directory
2. Parent directories (walking up to root)
3. `~/Code/host-uk/repos.yaml`
4. `~/.config/core/repos.yaml`
---
## After Setup
```bash
# Check workspace health
core dev health
# Full workflow (status + commit + push)
core dev work
# Build the project
core build
# Run tests
core go test # Go projects
core php test # PHP projects
```
---
## See Also
- [dev work](../dev/work/) - Multi-repo operations
- [build](../build/) - Build projects
- [doctor](../doctor/) - Check environment

View file

@ -1,125 +0,0 @@
# Claude Code Skill
The `core` CLI includes a Claude Code skill that helps Claude use the correct commands when working in host-uk repositories.
## What It Does
The skill provides Claude with:
- Command quick reference for all `core` commands
- Decision tree for choosing the right command
- Common mistakes to avoid
- Best practices for testing, building, and releasing
## Installation
### Automatic (Project-Based)
When working in any host-uk repository that includes `.claude/skills/core/`, Claude automatically discovers and uses the skill.
### Global Install
Install the skill globally so it works in any project:
```bash
# If you have the repo cloned
cd /path/to/core
./.claude/skills/core/install.sh
# Or via curl
curl -fsSL https://raw.githubusercontent.com/host-uk/core/main/.claude/skills/core/install.sh | bash
```
This copies the skill to `~/.claude/skills/core/`.
## Usage
### Automatic Invocation
Claude automatically uses the skill when:
- Running tests in a Go project
- Building or releasing
- Working across multiple repos
- Checking CI status or issues
### Manual Invocation
Type `/core` in Claude Code to see the full command reference.
## What Claude Learns
### Testing
```
Wrong: go test ./...
Right: core test
Why: core test sets MACOSX_DEPLOYMENT_TARGET, filters linker warnings,
and provides colour-coded coverage output.
```
### Building
```
Wrong: go build
Right: core build
Why: core build handles cross-compilation, code signing, archiving,
and checksums automatically.
```
### Multi-Repo Workflows
```
Wrong: cd into each repo, run git status
Right: core health
Why: Aggregated view across all repos in one command.
```
## Command Reference
The skill includes documentation for:
| Category | Commands |
|----------|----------|
| Testing | `core test`, `core test --coverage`, `core test --json` |
| Building | `core build`, `core build --targets`, `core build --ci` |
| Releasing | `core release`, `core sdk` |
| Multi-Repo | `core health`, `core work`, `core commit`, `core push`, `core pull` |
| GitHub | `core issues`, `core reviews`, `core ci` |
| Environment | `core doctor`, `core setup`, `core search`, `core install` |
| PHP | `core php dev`, `core php artisan` |
| Containers | `core run`, `core ps`, `core stop`, `core logs`, `core exec` |
| Docs | `core docs list`, `core docs sync` |
## Customisation
The skill is a markdown file at `.claude/skills/core/SKILL.md`. You can:
1. **Fork and modify** - Copy to your own repo's `.claude/skills/` and customise
2. **Extend** - Add project-specific commands or workflows
3. **Override** - Project skills take precedence over global skills
## Troubleshooting
### Skill Not Loading
Check if the skill exists:
```bash
ls ~/.claude/skills/core/SKILL.md
# or
ls .claude/skills/core/SKILL.md
```
### Reinstall
```bash
rm -rf ~/.claude/skills/core
curl -fsSL https://raw.githubusercontent.com/host-uk/core/main/.claude/skills/core/install.sh | bash
```
## See Also
- [test command](test.md) - Run tests with coverage
- [build command](build.md) - Build projects
- [work command](work.md) - Multi-repo operations

View file

@ -1,134 +0,0 @@
# core test
Run Go tests with coverage reporting and clean output.
## Usage
```bash
core test [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--verbose` | Stream test output as it runs |
| `--coverage` | Show detailed per-package coverage breakdown |
| `--pkg <pattern>` | Package pattern to test (default: `./...`) |
| `--run <regex>` | Run only tests matching this regex |
| `--short` | Skip long-running tests |
| `--race` | Enable race detector |
| `--json` | Output JSON for CI/agents |
## Examples
```bash
# Run all tests with coverage summary
core test
# Show test output as it runs
core test --verbose
# Show detailed coverage by package
core test --coverage
# Test specific packages
core test --pkg ./pkg/crypt
core test --pkg ./pkg/...
# Run specific tests by name
core test --run TestHash
core test --run "Test.*Good"
# Skip integration tests
core test --short
# Check for race conditions
core test --race
# CI/agent mode with JSON output
core test --json
```
## Output
### Default Output
```
Test: Running tests
Package: ./...
✓ 14 passed
Coverage: 75.1%
PASS All tests passed
```
### With `--coverage` Flag
```
Test: Running tests
Package: ./...
✓ 14 passed
Coverage by package:
pkg/crypt 91.2%
pkg/crypt/lthn 100.0%
pkg/io 96.0%
pkg/plugin 93.3%
pkg/runtime 83.3%
pkg/workspace 73.9%
pkg/container 65.6%
pkg/release 40.8%
pkg/php 26.0%
pkg/release/publishers 13.3%
Average 75.1%
PASS All tests passed
```
### JSON Output (`--json`)
```json
{
"passed": 14,
"failed": 0,
"skipped": 0,
"coverage": 75.1,
"exit_code": 0,
"failed_packages": []
}
```
## Features
### macOS Linker Warning Suppression
Sets `MACOSX_DEPLOYMENT_TARGET=26.0` automatically to suppress CGO linker warnings on macOS. The warnings are also filtered from output for clean DX.
### Coverage Colour Coding
Coverage percentages are colour-coded:
- **Green**: 80%+ coverage
- **Amber**: 50-79% coverage
- **Red**: Below 50% coverage
### Package Name Shortening
Package names are shortened for readability:
- `github.com/host-uk/core/pkg/crypt``pkg/crypt`
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | All tests passed |
| 1 | One or more tests failed |
## See Also
- [build command](build.md) - Build Go projects
- [doctor command](doctor.md) - Check development environment

View file

@ -0,0 +1,8 @@
# Test Examples
**Note:** Prefer `core go test` or `core php test` instead.
```bash
core test
core test --coverage
```

View file

@ -0,0 +1,74 @@
# core test
Run Go tests with coverage reporting.
Sets `MACOSX_DEPLOYMENT_TARGET=26.0` to suppress linker warnings on macOS.
## Usage
```bash
core test [flags]
```
## Flags
| Flag | Description |
|------|-------------|
| `--coverage` | Show detailed per-package coverage |
| `--json` | Output JSON for CI/agents |
| `--pkg` | Package pattern to test (default: ./...) |
| `--race` | Enable race detector |
| `--run` | Run only tests matching this regex |
| `--short` | Skip long-running tests |
| `--verbose` | Show test output as it runs |
## Examples
```bash
# Run all tests with coverage summary
core test
# Show test output as it runs
core test --verbose
# Detailed per-package coverage
core test --coverage
# Test specific packages
core test --pkg ./pkg/...
# Run specific test by name
core test --run TestName
# Run tests matching pattern
core test --run "Test.*Good"
# Skip long-running tests
core test --short
# Enable race detector
core test --race
# Output JSON for CI/agents
core test --json
```
## JSON Output
With `--json`, outputs structured results:
```json
{
"passed": 14,
"failed": 0,
"skipped": 0,
"coverage": 75.1,
"exit_code": 0,
"failed_packages": []
}
```
## See Also
- [go test](../go/test/) - Go-specific test options
- [go cov](../go/cov/) - Coverage reports

View file

@ -0,0 +1,52 @@
# VM Examples
## Running VMs
```bash
# Run image
core vm run server.iso
# Detached with resources
core vm run -d --memory 4096 --cpus 4 server.iso
# From template
core vm run --template core-dev --var SSH_KEY="ssh-rsa AAAA..."
```
## Management
```bash
# List running
core vm ps
# Include stopped
core vm ps -a
# Stop
core vm stop abc123
# View logs
core vm logs abc123
# Follow logs
core vm logs -f abc123
# Execute command
core vm exec abc123 ls -la
# Shell
core vm exec abc123 /bin/sh
```
## Templates
```bash
# List
core vm templates
# Show content
core vm templates show core-dev
# Show variables
core vm templates vars core-dev
```

View file

@ -0,0 +1,163 @@
# core vm
LinuxKit VM management.
LinuxKit VMs are lightweight, immutable VMs built from YAML templates.
They run using qemu or hyperkit depending on your system.
## Usage
```bash
core vm <command> [flags]
```
## Commands
| Command | Description |
|---------|-------------|
| [`run`](#vm-run) | Run a LinuxKit image or template |
| [`ps`](#vm-ps) | List running VMs |
| [`stop`](#vm-stop) | Stop a VM |
| [`logs`](#vm-logs) | View VM logs |
| [`exec`](#vm-exec) | Execute command in VM |
| [templates](templates/) | Manage LinuxKit templates |
---
## vm run
Run a LinuxKit image or build from a template.
```bash
core vm run <image> [flags]
core vm run --template <name> [flags]
```
Supported image formats: `.iso`, `.qcow2`, `.vmdk`, `.raw`
### Flags
| Flag | Description |
|------|-------------|
| `--template` | Run from a LinuxKit template (build + run) |
| `--var` | Template variable in KEY=VALUE format (repeatable) |
| `--name` | Name for the container |
| `--memory` | Memory in MB (default: 1024) |
| `--cpus` | CPU count (default: 1) |
| `--ssh-port` | SSH port for exec commands (default: 2222) |
| `-d` | Run in detached mode (background) |
### Examples
```bash
# Run from image file
core vm run image.iso
# Run detached with more resources
core vm run -d image.qcow2 --memory 2048 --cpus 4
# Run from template
core vm run --template core-dev --var SSH_KEY="ssh-rsa AAAA..."
# Multiple template variables
core vm run --template server-php --var SSH_KEY="..." --var DOMAIN=example.com
```
---
## vm ps
List running VMs.
```bash
core vm ps [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `-a` | Show all (including stopped) |
### Output
```
ID NAME IMAGE STATUS STARTED PID
abc12345 myvm ...core-dev.qcow2 running 5m 12345
```
---
## vm stop
Stop a running VM by ID or name.
```bash
core vm stop <id>
```
Supports partial ID matching.
### Examples
```bash
# Full ID
core vm stop abc12345678
# Partial ID
core vm stop abc1
```
---
## vm logs
View VM logs.
```bash
core vm logs <id> [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `-f` | Follow log output |
### Examples
```bash
# View logs
core vm logs abc12345
# Follow logs
core vm logs -f abc1
```
---
## vm exec
Execute a command in a running VM via SSH.
```bash
core vm exec <id> <command...>
```
### Examples
```bash
# List files
core vm exec abc12345 ls -la
# Open shell
core vm exec abc1 /bin/sh
```
---
## See Also
- [templates](templates/) - Manage LinuxKit templates
- [build](../build/) - Build LinuxKit images
- [dev](../dev/) - Dev environment management

View file

@ -0,0 +1,53 @@
# VM Templates Examples
## List
```bash
core vm templates
```
## Show
```bash
core vm templates show core-dev
```
## Variables
```bash
core vm templates vars core-dev
```
## Output
```
Variables for core-dev:
SSH_KEY (required) SSH public key
MEMORY (optional) Memory in MB (default: 4096)
CPUS (optional) CPU count (default: 4)
```
## Using Templates
```bash
core vm run --template core-dev --var SSH_KEY="ssh-rsa AAAA..."
```
## Template Format
`.core/linuxkit/myserver.yml`:
```yaml
kernel:
image: linuxkit/kernel:5.15
cmdline: "console=tty0"
init:
- linuxkit/init:v1.0.0
services:
- name: sshd
image: linuxkit/sshd:v1.0.0
- name: myapp
image: ghcr.io/myorg/myapp:latest
```

View file

@ -1,11 +1,11 @@
# core templates
# core vm templates
Manage LinuxKit templates for container images.
## Usage
```bash
core templates [command]
core vm templates [command]
```
## Commands
@ -14,13 +14,14 @@ core templates [command]
|---------|-------------|
| `list` | List available templates |
| `show` | Show template details |
| `vars` | Show template variables |
## templates list
List all available LinuxKit templates.
```bash
core templates list
core vm templates list
```
### Output
@ -46,13 +47,13 @@ Available Templates:
Show details of a specific template.
```bash
core templates show <name>
core vm templates show <name>
```
### Example
```bash
core templates show core-dev
core vm templates show core-dev
```
Output:
@ -77,6 +78,28 @@ Services:
Size: ~1.8GB
```
## templates vars
Show variables defined by a template.
```bash
core vm templates vars <name>
```
### Example
```bash
core vm templates vars core-dev
```
Output:
```
Variables for core-dev:
SSH_KEY (required) SSH public key
MEMORY (optional) Memory in MB (default: 4096)
CPUS (optional) CPU count (default: 4)
```
## Template Locations
Templates are searched in order:
@ -87,31 +110,15 @@ Templates are searched in order:
## Creating Templates
Create a LinuxKit YAML in `.core/linuxkit/`:
```yaml
# .core/linuxkit/myserver.yml
kernel:
image: linuxkit/kernel:5.15
cmdline: "console=tty0"
init:
- linuxkit/init:v1.0.0
services:
- name: sshd
image: linuxkit/sshd:v1.0.0
- name: myapp
image: ghcr.io/myorg/myapp:latest
```
Create a LinuxKit YAML in `.core/linuxkit/`. See [Template Format](example.md#template-format) for examples.
Run with:
```bash
core run --template myserver
core vm run --template myserver
```
## See Also
- [run command](run.md) - Run LinuxKit images
- [build command](build.md) - Build LinuxKit images
- [vm command](../) - Run LinuxKit images
- [build command](../../build/) - Build LinuxKit images

View file

@ -1,160 +0,0 @@
# core work
Multi-repo git operations for managing the host-uk organization.
## Overview
The `work` command and related commands (`health`, `issues`, `reviews`, `commit`, `push`, `pull`, `impact`, `ci`) help manage multiple repositories in the host-uk ecosystem simultaneously.
## Commands
| Command | Description |
|---------|-------------|
| `core work` | Multi-repo git operations |
| `core health` | Quick health check across all repos |
| `core issues` | List open issues across all repos |
| `core reviews` | List PRs needing review |
| `core commit` | Claude-assisted commits across repos |
| `core push` | Push commits across all repos |
| `core pull` | Pull updates across all repos |
| `core impact` | Show impact of changing a repo |
| `core ci` | Check CI status across all repos |
## core health
Quick health check showing status of all repos.
```bash
core health
```
Output shows:
- Git status (clean/dirty)
- Current branch
- Commits ahead/behind remote
- CI status
## core issues
List open issues across all repositories.
```bash
core issues [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--assignee` | Filter by assignee |
| `--label` | Filter by label |
| `--limit` | Max issues per repo |
## core reviews
List pull requests needing review.
```bash
core reviews [flags]
```
Shows PRs where:
- You are a requested reviewer
- PR is open and not draft
- CI is passing
## core commit
Create commits across repos with Claude assistance.
```bash
core commit [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--message` | Commit message (auto-generated if not provided) |
| `--all` | Commit in all dirty repos |
Claude analyzes changes and suggests conventional commit messages.
## core push
Push commits across all repos.
```bash
core push [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--all` | Push all repos with unpushed commits |
| `--force` | Force push (use with caution) |
## core pull
Pull updates across all repos.
```bash
core pull [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--all` | Pull all repos |
| `--rebase` | Rebase instead of merge |
## core impact
Show the impact of changing a repository.
```bash
core impact <repo>
```
Shows:
- Dependent repos
- Reverse dependencies
- Potential breaking changes
## core ci
Check CI status across all repos.
```bash
core ci [flags]
```
### Flags
| Flag | Description |
|------|-------------|
| `--watch` | Watch for status changes |
| `--failing` | Show only failing repos |
## Registry
These commands use `repos.yaml` to know which repos to manage:
```yaml
repos:
- name: core
path: ./core
url: https://github.com/host-uk/core
- name: core-php
path: ./core-php
url: https://github.com/host-uk/core-php
```
Use `core setup` to clone all repos from the registry.
## See Also
- [setup command](setup.md) - Clone repos from registry
- [search command](search.md) - Find and install repos

View file

@ -205,14 +205,148 @@ files:
port: 8080
```
## repos.yaml
Package registry for multi-repo workspaces:
```yaml
# Organisation name (used for GitHub URLs)
org: host-uk
# Base path for cloning (default: current directory)
base_path: .
# Default settings for all repos
defaults:
ci: github
license: EUPL-1.2
branch: main
# Repository definitions
repos:
# Foundation packages (no dependencies)
core-php:
type: foundation
description: Foundation framework
core-devops:
type: foundation
description: Development environment
clone: false # Skip during setup (already exists)
# Module packages (depend on foundation)
core-tenant:
type: module
depends_on: [core-php]
description: Multi-tenancy module
core-admin:
type: module
depends_on: [core-php, core-tenant]
description: Admin panel
core-api:
type: module
depends_on: [core-php]
description: REST API framework
# Product packages (user-facing applications)
core-bio:
type: product
depends_on: [core-php, core-tenant]
description: Link-in-bio product
domain: bio.host.uk.com
core-social:
type: product
depends_on: [core-php, core-tenant]
description: Social scheduling
domain: social.host.uk.com
# Templates
core-template:
type: template
description: Starter template for new projects
```
### repos.yaml Fields
| Field | Required | Description |
|-------|----------|-------------|
| `org` | Yes | GitHub organisation name |
| `base_path` | No | Directory for cloning (default: `.`) |
| `defaults` | No | Default settings applied to all repos |
| `repos` | Yes | Map of repository definitions |
### Repository Fields
| Field | Required | Description |
|-------|----------|-------------|
| `type` | Yes | `foundation`, `module`, `product`, or `template` |
| `description` | No | Human-readable description |
| `depends_on` | No | List of package dependencies |
| `clone` | No | Set `false` to skip during setup |
| `domain` | No | Production domain (for products) |
| `branch` | No | Override default branch |
### Package Types
| Type | Description | Dependencies |
|------|-------------|--------------|
| `foundation` | Core framework packages | None |
| `module` | Reusable modules | Foundation packages |
| `product` | User-facing applications | Foundation + modules |
| `template` | Starter templates | Any |
---
## Environment Variables
Complete reference of environment variables used by Core CLI.
### Authentication
| Variable | Used By | Description |
|----------|---------|-------------|
| `GITHUB_TOKEN` | `core ci`, `core dev` | GitHub API authentication |
| `ANTHROPIC_API_KEY` | `core ai`, `core dev claude` | Claude API key |
| `AGENTIC_TOKEN` | `core ai task*` | Agentic API authentication |
| `AGENTIC_BASE_URL` | `core ai task*` | Agentic API endpoint |
### Publishing
| Variable | Used By | Description |
|----------|---------|-------------|
| `NPM_TOKEN` | `core ci` (npm publisher) | npm registry auth token |
| `CHOCOLATEY_API_KEY` | `core ci` (chocolatey publisher) | Chocolatey API key |
| `DOCKER_USERNAME` | `core ci` (docker publisher) | Docker registry username |
| `DOCKER_PASSWORD` | `core ci` (docker publisher) | Docker registry password |
### Deployment
| Variable | Used By | Description |
|----------|---------|-------------|
| `COOLIFY_URL` | `core php deploy` | Coolify server URL |
| `COOLIFY_TOKEN` | `core php deploy` | Coolify API token |
| `COOLIFY_APP_ID` | `core php deploy` | Production application ID |
| `COOLIFY_STAGING_APP_ID` | `core php deploy --staging` | Staging application ID |
### Build
| Variable | Used By | Description |
|----------|---------|-------------|
| `CGO_ENABLED` | `core build`, `core go *` | Enable/disable CGO (default: 0) |
| `GOOS` | `core build` | Target operating system |
| `GOARCH` | `core build` | Target architecture |
### Configuration Paths
| Variable | Description |
|----------|-------------|
| `GITHUB_TOKEN` | GitHub authentication (via gh CLI) |
| `NPM_TOKEN` | npm publish token |
| `CHOCOLATEY_API_KEY` | Chocolatey publish key |
| `COOLIFY_TOKEN` | Coolify deployment token |
| `CORE_CONFIG` | Override config directory (default: `~/.core/`) |
| `CORE_REGISTRY` | Override repos.yaml path |
---
## Defaults

View file

@ -1,134 +0,0 @@
# Architecture
Core follows a modular, service-based architecture designed for maintainability and testability.
## Overview
```
┌─────────────────────────────────────────────────────────┐
│ Wails Application │
├─────────────────────────────────────────────────────────┤
│ Core │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Display │ │ WebView │ │ MCP │ │ Config │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Crypt │ │ I18n │ │ IO │ │Workspace │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────┤
│ Plugin System │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Plugin A │ │ Plugin B │ │ Plugin C │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
```
## Core Container
The `Core` struct is the central service container:
```go
type Core struct {
services map[string]any // Service registry
actions []ActionHandler // IPC handlers
Features *Features // Feature flags
servicesLocked bool // Prevent late registration
}
```
### Service Registration
Services are registered using factory functions:
```go
core.New(
core.WithService(display.NewService), // Auto-discovered name
core.WithName("custom", myFactory), // Explicit name
)
```
### Service Retrieval
Type-safe service retrieval:
```go
// Returns error if not found
svc, err := core.ServiceFor[*display.Service](c, "display")
// Panics if not found (use in init code)
svc := core.MustServiceFor[*display.Service](c, "display")
```
## Service Lifecycle
Services can implement lifecycle interfaces:
```go
// Called when app starts
type Startable interface {
OnStartup(ctx context.Context) error
}
// Called when app shuts down
type Stoppable interface {
OnShutdown(ctx context.Context) error
}
```
## IPC / Actions
Services communicate via the action system:
```go
// Register a handler
c.RegisterAction(func(c *core.Core, msg core.Message) error {
if msg.Type == "my-action" {
// Handle message
}
return nil
})
// Send a message
c.ACTION(core.Message{
Type: "my-action",
Data: map[string]any{"key": "value"},
})
```
## Frontend Bindings
Wails generates TypeScript bindings automatically:
```typescript
// Auto-generated from Go service
import { ShowNotification } from '@bindings/display/service';
await ShowNotification({
title: "Hello",
message: "From TypeScript!"
});
```
## Package Structure
```
pkg/
├── core/ # Core container and interfaces
├── display/ # Window, tray, dialogs, clipboard
├── webview/ # JS execution, DOM, screenshots
├── mcp/ # Model Context Protocol server
├── config/ # Configuration persistence
├── crypt/ # Encryption and signing
├── i18n/ # Internationalization
├── io/ # File system helpers
├── workspace/ # Project management
├── plugin/ # Plugin system
└── module/ # Module system
```
## Design Principles
1. **Dependency Injection**: Services receive dependencies via constructor
2. **Interface Segregation**: Small, focused interfaces
3. **Testability**: All services are mockable
4. **No Globals**: State contained in Core instance

View file

@ -1,122 +0,0 @@
# Config Service
The Config service (`pkg/config`) provides unified configuration management with automatic persistence, feature flags, and XDG-compliant directory paths.
## Features
- JSON configuration with auto-save
- Feature flag management
- XDG Base Directory support
- Struct serialization helpers
- Type-safe get/set operations
## Basic Usage
```go
import "github.com/Snider/Core/pkg/config"
// Standalone usage
cfg, err := config.New()
if err != nil {
log.Fatal(err)
}
// With Core framework
c, _ := core.New(
core.WithService(config.Register),
)
cfg := core.MustServiceFor[*config.Service](c, "config")
```
## Get & Set Values
```go
// Set a value (auto-saves)
err := cfg.Set("language", "fr")
// Get a value
var lang string
err := cfg.Get("language", &lang)
```
Available configuration keys:
| Key | Type | Description |
|-----|------|-------------|
| `language` | string | UI language code |
| `default_route` | string | Default navigation route |
| `configDir` | string | Config files directory |
| `dataDir` | string | Data files directory |
| `cacheDir` | string | Cache directory |
| `workspaceDir` | string | Workspaces directory |
## Feature Flags
```go
// Enable a feature
cfg.EnableFeature("dark_mode")
// Check if enabled
if cfg.IsFeatureEnabled("dark_mode") {
// Apply dark theme
}
// Disable a feature
cfg.DisableFeature("dark_mode")
```
## Struct Serialization
Store complex data structures in separate JSON files:
```go
type UserPrefs struct {
Theme string `json:"theme"`
Notifications bool `json:"notifications"`
}
// Save struct to config/user_prefs.json
prefs := UserPrefs{Theme: "dark", Notifications: true}
err := cfg.SaveStruct("user_prefs", prefs)
// Load struct from file
var loaded UserPrefs
err := cfg.LoadStruct("user_prefs", &loaded)
```
## Directory Paths
The service automatically creates XDG-compliant directories:
```go
// Access directory paths
fmt.Println(cfg.ConfigDir) // ~/.config/lethean or ~/lethean/config
fmt.Println(cfg.DataDir) // Data storage
fmt.Println(cfg.CacheDir) // Cache files
fmt.Println(cfg.WorkspaceDir) // User workspaces
```
## Manual Save
Changes are auto-saved, but you can save explicitly:
```go
err := cfg.Save()
```
## Frontend Usage (TypeScript)
```typescript
import { Get, Set, IsFeatureEnabled } from '@bindings/config/service';
// Get configuration
const lang = await Get("language");
// Set configuration
await Set("default_route", "/dashboard");
// Check feature flag
if (await IsFeatureEnabled("dark_mode")) {
applyDarkTheme();
}
```

View file

@ -1,312 +0,0 @@
# Core API Reference
Complete API reference for the Core framework (`pkg/core`).
## Core Struct
The central application container.
### Creation
```go
func New(opts ...Option) (*Core, error)
```
Creates a new Core instance with the specified options.
### Methods
#### Service Access
```go
func ServiceFor[T any](c *Core, name string) (T, error)
```
Retrieves a service by name with type safety.
```go
func MustServiceFor[T any](c *Core, name string) T
```
Retrieves a service by name, panics if not found or wrong type.
#### Actions
```go
func (c *Core) ACTION(msg Message) error
```
Broadcasts a message to all registered action handlers.
```go
func (c *Core) RegisterAction(handler func(*Core, Message) error)
```
Registers an action handler.
#### Service Registration
```go
func (c *Core) AddService(name string, svc any) error
```
Manually adds a service to the registry.
#### Config Access
```go
func (c *Core) Config() *config.Service
```
Returns the config service if registered.
## Options
### WithService
```go
func WithService(factory ServiceFactory) Option
```
Registers a service using its factory function.
```go
c, _ := core.New(
core.WithService(config.Register),
core.WithService(display.NewService),
)
```
### WithName
```go
func WithName(name string, factory ServiceFactory) Option
```
Registers a service with an explicit name.
```go
c, _ := core.New(
core.WithName("mydb", database.NewService),
)
```
### WithAssets
```go
func WithAssets(assets embed.FS) Option
```
Sets embedded assets for the application.
### WithServiceLock
```go
func WithServiceLock() Option
```
Prevents late service registration after initialization.
## ServiceFactory
```go
type ServiceFactory func(c *Core) (any, error)
```
Factory function signature for service creation.
## Message
```go
type Message interface{}
```
Messages can be any type. Common patterns:
```go
// Map-based message
c.ACTION(map[string]any{
"action": "user.created",
"id": "123",
})
// Typed message
type UserCreated struct {
ID string
Email string
}
c.ACTION(UserCreated{ID: "123", Email: "user@example.com"})
```
## ServiceRuntime
Generic helper for services that need Core access.
```go
type ServiceRuntime[T any] struct {
core *Core
options T
}
```
### Creation
```go
func NewServiceRuntime[T any](c *Core, opts T) *ServiceRuntime[T]
```
### Methods
```go
func (r *ServiceRuntime[T]) Core() *Core
func (r *ServiceRuntime[T]) Options() T
func (r *ServiceRuntime[T]) Config() *config.Service
```
### Usage
```go
type MyOptions struct {
Timeout time.Duration
}
type MyService struct {
*core.ServiceRuntime[MyOptions]
}
func NewMyService(c *core.Core) (any, error) {
opts := MyOptions{Timeout: 30 * time.Second}
return &MyService{
ServiceRuntime: core.NewServiceRuntime(c, opts),
}, nil
}
func (s *MyService) DoSomething() {
timeout := s.Options().Timeout
cfg := s.Config()
// ...
}
```
## Lifecycle Interfaces
### Startable
```go
type Startable interface {
OnStartup(ctx context.Context) error
}
```
Implement for initialization on app start.
### Stoppable
```go
type Stoppable interface {
OnShutdown(ctx context.Context) error
}
```
Implement for cleanup on app shutdown.
### IPC Handler
```go
type IPCHandler interface {
HandleIPCEvents(c *Core, msg Message) error
}
```
Automatically registered when using `WithService`.
## Built-in Actions
### ActionServiceStartup
```go
type ActionServiceStartup struct{}
```
Sent to all services when application starts.
### ActionServiceShutdown
```go
type ActionServiceShutdown struct{}
```
Sent to all services when application shuts down.
## Error Helpers
```go
func E(service, operation string, err error) error
```
Creates a contextual error with service and operation info.
```go
if err != nil {
return core.E("myservice", "Connect", err)
}
// Error: myservice.Connect: connection refused
```
## Complete Example
```go
package main
import (
"context"
"github.com/Snider/Core/pkg/core"
"github.com/Snider/Core/pkg/config"
)
type MyService struct {
*core.ServiceRuntime[struct{}]
data string
}
func NewMyService(c *core.Core) (any, error) {
return &MyService{
ServiceRuntime: core.NewServiceRuntime(c, struct{}{}),
data: "initialized",
}, nil
}
func (s *MyService) OnStartup(ctx context.Context) error {
// Startup logic
return nil
}
func (s *MyService) OnShutdown(ctx context.Context) error {
// Cleanup logic
return nil
}
func (s *MyService) HandleIPCEvents(c *core.Core, msg core.Message) error {
switch m := msg.(type) {
case map[string]any:
if m["action"] == "myservice.update" {
s.data = m["data"].(string)
}
}
return nil
}
func main() {
c, err := core.New(
core.WithService(config.Register),
core.WithService(NewMyService),
core.WithServiceLock(),
)
if err != nil {
panic(err)
}
svc := core.MustServiceFor[*MyService](c, "main")
_ = svc
}
```

View file

@ -1,133 +0,0 @@
# Crypt Service
The Crypt service (`pkg/crypt`) provides cryptographic utilities including hashing, checksums, RSA encryption, and PGP operations.
## Features
- Multiple hash algorithms (SHA512, SHA256, SHA1, MD5)
- Checksum functions (Fletcher, Luhn)
- RSA key generation and encryption
- PGP encryption, signing, and verification
- Symmetric PGP encryption
## Basic Usage
```go
import "github.com/Snider/Core/pkg/crypt"
// Standalone usage
crypto, err := crypt.New()
// With Core framework
c, _ := core.New(
core.WithService(crypt.Register),
)
crypto := core.MustServiceFor[*crypt.Service](c, "crypt")
```
## Hashing
```go
// Available algorithms: SHA512, SHA256, SHA1, MD5, LTHN
hash := crypto.Hash(crypt.SHA256, "hello world")
// Check if string is valid hash algorithm
isValid := crypto.IsHashAlgo("sha256")
```
## Checksums
```go
// Luhn validation (credit card numbers)
isValid := crypto.Luhn("4532015112830366")
// Fletcher checksums
f16 := crypto.Fletcher16("data")
f32 := crypto.Fletcher32("data")
f64 := crypto.Fletcher64("data")
```
## RSA Encryption
```go
// Generate key pair (2048 or 4096 bits recommended)
publicKey, privateKey, err := crypto.GenerateRSAKeyPair(2048)
// Encrypt with public key
ciphertext, err := crypto.EncryptRSA(publicKey, "secret message")
// Decrypt with private key
plaintext, err := crypto.DecryptRSA(privateKey, ciphertext)
```
## PGP Encryption
### Key Generation
```go
// Generate PGP key pair
publicKey, privateKey, err := crypto.GeneratePGPKeyPair(
"User Name",
"user@example.com",
"Key comment",
)
```
### Asymmetric Encryption
```go
// Encrypt for recipient
ciphertext, err := crypto.EncryptPGPToString(recipientPublicKey, "secret data")
// Decrypt with private key
plaintext, err := crypto.DecryptPGP(privateKey, ciphertext)
```
### Symmetric Encryption
```go
var buf bytes.Buffer
err := crypto.SymmetricallyEncryptPGP(&buf, "data", "passphrase")
```
### Signing & Verification
```go
// Sign data
signature, err := crypto.SignPGP(privateKey, "data to sign")
// Verify signature
err := crypto.VerifyPGP(publicKey, "data to sign", signature)
if err != nil {
// Signature invalid
}
```
## Hash Types
| Constant | Algorithm |
|----------|-----------|
| `crypt.SHA512` | SHA-512 |
| `crypt.SHA256` | SHA-256 |
| `crypt.SHA1` | SHA-1 |
| `crypt.MD5` | MD5 |
| `crypt.LTHN` | Custom LTHN hash |
## Frontend Usage (TypeScript)
```typescript
import {
Hash,
GenerateRSAKeyPair,
EncryptRSA,
DecryptRSA
} from '@bindings/crypt/service';
// Hash data
const hash = await Hash("SHA256", "hello world");
// RSA encryption
const { publicKey, privateKey } = await GenerateRSAKeyPair(2048);
const encrypted = await EncryptRSA(publicKey, "secret");
const decrypted = await DecryptRSA(privateKey, encrypted);
```

View file

@ -1,352 +0,0 @@
# Display API Reference
Complete API reference for the Display service (`pkg/display`).
## Service Creation
```go
func NewService(c *core.Core) (any, error)
```
## Window Management
### CreateWindow
```go
func (s *Service) CreateWindow(opts CreateWindowOptions) (*WindowInfo, error)
```
Creates a new window with the specified options.
```go
type CreateWindowOptions struct {
Name string
Title string
URL string
X int
Y int
Width int
Height int
}
```
### CloseWindow
```go
func (s *Service) CloseWindow(name string) error
```
### GetWindowInfo
```go
func (s *Service) GetWindowInfo(name string) (*WindowInfo, error)
```
Returns:
```go
type WindowInfo struct {
Name string
Title string
X int
Y int
Width int
Height int
IsVisible bool
IsFocused bool
IsMaximized bool
IsMinimized bool
}
```
### ListWindowInfos
```go
func (s *Service) ListWindowInfos() []*WindowInfo
```
### Window Position & Size
```go
func (s *Service) SetWindowPosition(name string, x, y int) error
func (s *Service) SetWindowSize(name string, width, height int) error
func (s *Service) SetWindowBounds(name string, x, y, width, height int) error
```
### Window State
```go
func (s *Service) MaximizeWindow(name string) error
func (s *Service) MinimizeWindow(name string) error
func (s *Service) RestoreWindow(name string) error
func (s *Service) FocusWindow(name string) error
func (s *Service) SetWindowFullscreen(name string, fullscreen bool) error
func (s *Service) SetWindowAlwaysOnTop(name string, onTop bool) error
func (s *Service) SetWindowVisibility(name string, visible bool) error
```
### Window Title
```go
func (s *Service) SetWindowTitle(name, title string) error
func (s *Service) GetWindowTitle(name string) (string, error)
```
### Window Background
```go
func (s *Service) SetWindowBackgroundColour(name string, r, g, b, a uint8) error
```
### Focus
```go
func (s *Service) GetFocusedWindow() string
```
## Screen Management
### GetScreens
```go
func (s *Service) GetScreens() []*Screen
```
Returns:
```go
type Screen struct {
ID string
Name string
X int
Y int
Width int
Height int
ScaleFactor float64
IsPrimary bool
}
```
### GetScreen
```go
func (s *Service) GetScreen(id string) (*Screen, error)
```
### GetPrimaryScreen
```go
func (s *Service) GetPrimaryScreen() (*Screen, error)
```
### GetScreenAtPoint
```go
func (s *Service) GetScreenAtPoint(x, y int) (*Screen, error)
```
### GetScreenForWindow
```go
func (s *Service) GetScreenForWindow(name string) (*Screen, error)
```
### GetWorkAreas
```go
func (s *Service) GetWorkAreas() []*WorkArea
```
Returns usable screen space (excluding dock/taskbar).
## Layout Management
### SaveLayout / RestoreLayout
```go
func (s *Service) SaveLayout(name string) error
func (s *Service) RestoreLayout(name string) error
func (s *Service) ListLayouts() []string
func (s *Service) DeleteLayout(name string) error
func (s *Service) GetLayout(name string) *Layout
```
### TileWindows
```go
func (s *Service) TileWindows(mode TileMode, windows []string) error
```
Tile modes:
```go
const (
TileModeLeft TileMode = "left"
TileModeRight TileMode = "right"
TileModeGrid TileMode = "grid"
TileModeQuadrants TileMode = "quadrants"
)
```
### SnapWindow
```go
func (s *Service) SnapWindow(name string, position SnapPosition) error
```
Snap positions:
```go
const (
SnapPositionLeft SnapPosition = "left"
SnapPositionRight SnapPosition = "right"
SnapPositionTop SnapPosition = "top"
SnapPositionBottom SnapPosition = "bottom"
SnapPositionTopLeft SnapPosition = "top-left"
SnapPositionTopRight SnapPosition = "top-right"
SnapPositionBottomLeft SnapPosition = "bottom-left"
SnapPositionBottomRight SnapPosition = "bottom-right"
)
```
### StackWindows
```go
func (s *Service) StackWindows(windows []string, offsetX, offsetY int) error
```
### ApplyWorkflowLayout
```go
func (s *Service) ApplyWorkflowLayout(workflow WorkflowType) error
```
Workflow types:
```go
const (
WorkflowCoding WorkflowType = "coding"
WorkflowDebugging WorkflowType = "debugging"
WorkflowPresenting WorkflowType = "presenting"
)
```
## Dialogs
### File Dialogs
```go
func (s *Service) OpenSingleFileDialog(opts OpenFileOptions) (string, error)
func (s *Service) OpenFileDialog(opts OpenFileOptions) ([]string, error)
func (s *Service) SaveFileDialog(opts SaveFileOptions) (string, error)
func (s *Service) OpenDirectoryDialog(opts OpenDirectoryOptions) (string, error)
```
Options:
```go
type OpenFileOptions struct {
Title string
DefaultDirectory string
AllowMultiple bool
Filters []FileFilter
}
type SaveFileOptions struct {
Title string
DefaultDirectory string
DefaultFilename string
Filters []FileFilter
}
type FileFilter struct {
DisplayName string
Pattern string // e.g., "*.png;*.jpg"
}
```
### ConfirmDialog
```go
func (s *Service) ConfirmDialog(title, message string) (bool, error)
```
### PromptDialog
```go
func (s *Service) PromptDialog(title, message string) (string, bool, error)
```
## System Tray
```go
func (s *Service) SetTrayIcon(icon []byte) error
func (s *Service) SetTrayTooltip(tooltip string) error
func (s *Service) SetTrayLabel(label string) error
func (s *Service) SetTrayMenu(items []TrayMenuItem) error
func (s *Service) GetTrayInfo() map[string]any
```
Menu item:
```go
type TrayMenuItem struct {
Label string
ActionID string
IsSeparator bool
}
```
## Clipboard
```go
func (s *Service) ReadClipboard() (string, error)
func (s *Service) WriteClipboard(text string) error
func (s *Service) HasClipboard() bool
func (s *Service) ClearClipboard() error
```
## Notifications
```go
func (s *Service) ShowNotification(opts NotificationOptions) error
func (s *Service) ShowInfoNotification(title, message string) error
func (s *Service) ShowWarningNotification(title, message string) error
func (s *Service) ShowErrorNotification(title, message string) error
func (s *Service) RequestNotificationPermission() (bool, error)
func (s *Service) CheckNotificationPermission() (bool, error)
```
Options:
```go
type NotificationOptions struct {
ID string
Title string
Message string
Subtitle string
}
```
## Theme
```go
func (s *Service) GetTheme() *Theme
func (s *Service) GetSystemTheme() string
```
Returns:
```go
type Theme struct {
IsDark bool
}
```
## Events
```go
func (s *Service) GetEventManager() *EventManager
```
The EventManager handles WebSocket connections for real-time events.

View file

@ -1,54 +0,0 @@
---
title: e
---
# Service: `e`
Package e provides a standardized error handling mechanism for the Core library.
It allows for wrapping errors with contextual information, making it easier to
trace the origin of an error and provide meaningful feedback.
The design of this package is influenced by the need for a simple, yet powerful
way to handle errors that can occur in different layers of the application,
from low-level file operations to high-level service interactions.
The key features of this package are:
- Error wrapping: The Op and an optional Msg field provide context about
where and why an error occurred.
- Stack traces: By wrapping errors, we can build a logical stack trace
that is more informative than a raw stack trace.
- Consistent error handling: Encourages a uniform approach to error
handling across the entire codebase.
## Types
### `type Error`
`Error` represents a standardized error with operational context.
```go
type Error struct {
// Op is the operation being performed, e.g., "config.Load".
Op string
// Msg is a human-readable message explaining the error.
Msg string
// Err is the underlying error that was wrapped.
Err error
}
```
#### Methods
- `Error() string`: Error returns the string representation of the error.
- `Unwrap() error`: Unwrap provides compatibility for Go's errors.Is and errors.As functions.
## Functions
- `E(op, msg string, err error) error`: E is a helper function to create a new Error.
This is the primary way to create errors that will be consumed by the system. For example:
```go
return e.E("config.Load", "failed to load config file", err)
```
The `op` parameter should be in the format of `package.function` or `service.method`. The `msg` parameter should be a human-readable message that can be displayed to the user. The `err` parameter is the underlying error that is being wrapped.

View file

@ -1,152 +0,0 @@
# Help Service
The Help service (`pkg/help`) provides an embeddable documentation system that displays MkDocs-based help content in a dedicated window.
## Features
- Embedded help content (MkDocs static site)
- Context-sensitive help navigation
- Works with or without Display service
- Multiple content sources (embedded, filesystem, custom)
## Basic Usage
```go
import "github.com/Snider/Core/pkg/help"
// Create with default embedded content
helpService, err := help.New(help.Options{})
// Initialize with core dependencies
helpService.Init(coreInstance, displayService)
```
## Showing Help
```go
// Show main help window
err := helpService.Show()
// Show specific section
err := helpService.ShowAt("getting-started")
err := helpService.ShowAt("api/config")
```
## Options
```go
type Options struct {
Source string // Path to help content directory
Assets fs.FS // Custom filesystem for assets
}
```
### Default Embedded Content
```go
// Uses embedded MkDocs site
helpService, _ := help.New(help.Options{})
```
### Custom Directory
```go
// Use local directory
helpService, _ := help.New(help.Options{
Source: "/path/to/docs/site",
})
```
### Custom Filesystem
```go
//go:embed docs/*
var docsFS embed.FS
helpService, _ := help.New(help.Options{
Assets: docsFS,
})
```
## Integration with Core
The help service can work standalone or integrated with Core:
### With Display Service
When Display service is available, help opens through the IPC action system:
```go
// Automatically uses display.open_window action
helpService.Init(core, displayService)
helpService.Show()
```
### Without Display Service
Falls back to direct Wails window creation:
```go
// Creates window directly via Wails
helpService.Init(core, nil)
helpService.Show()
```
## Lifecycle
```go
// Called on application startup
err := helpService.ServiceStartup(ctx)
```
## Building Help Content
Help content is a static MkDocs site. To update:
1. Edit documentation in `docs/` directory
2. Build with MkDocs:
```bash
mkdocs build
```
3. The built site goes to `pkg/help/public/`
4. Content is embedded at compile time
## Frontend Usage (TypeScript)
```typescript
import { Show, ShowAt } from '@bindings/help/service';
// Open help window
await Show();
// Open specific section
await ShowAt("configuration");
await ShowAt("api/display");
```
## Help Window Options
The help window opens with default settings:
| Property | Value |
|----------|-------|
| Title | "Help" |
| Width | 800px |
| Height | 600px |
## IPC Action
When using Display service, help triggers this action:
```go
{
"action": "display.open_window",
"name": "help",
"options": {
"Title": "Help",
"Width": 800,
"Height": 600,
"URL": "/#anchor", // When using ShowAt
},
}
```

View file

@ -1,130 +0,0 @@
# I18n Service
The I18n service (`pkg/i18n`) provides internationalization and localization support with automatic language detection and template-based translations.
## Features
- JSON-based locale files
- Embedded locale bundles
- Automatic language detection from environment
- Template variable interpolation
- BCP 47 language tag support
## Basic Usage
```go
import "github.com/Snider/Core/pkg/i18n"
// Create service (defaults to English)
i18n, err := i18n.New()
if err != nil {
log.Fatal(err)
}
```
## Setting Language
```go
// Set language using BCP 47 tag
err := i18n.SetLanguage("fr")
err := i18n.SetLanguage("en-US")
err := i18n.SetLanguage("zh-Hans")
```
## Translating Messages
```go
// Simple translation
msg := i18n.Translate("welcome_message")
// With template data
msg := i18n.Translate("greeting", map[string]string{
"Name": "John",
})
// Template: "Hello, {{.Name}}!"
// Result: "Hello, John!"
```
## Available Languages
```go
// Get list of available language codes
langs := i18n.AvailableLanguages()
// Returns: ["en", "es", "fr", "de", ...]
```
## Get All Messages
```go
// Get all translations for a language
messages, err := i18n.GetAllMessages("en")
for key, value := range messages {
fmt.Printf("%s: %s\n", key, value)
}
```
## Locale File Format
Locale files are JSON stored in `locales/` directory:
```json
// locales/en.json
{
"welcome": "Welcome to the application",
"greeting": "Hello, {{.Name}}!",
"items_count": {
"one": "{{.Count}} item",
"other": "{{.Count}} items"
}
}
```
## Adding New Languages
1. Create a new JSON file in `pkg/i18n/locales/`:
```
locales/es.json
```
2. Add translations:
```json
{
"welcome": "Bienvenido a la aplicación",
"greeting": "¡Hola, {{.Name}}!"
}
```
3. The service automatically loads embedded locales at startup.
## Language Detection
The service can detect system language from the `LANG` environment variable:
```go
// Automatic detection happens internally
// LANG=fr_FR.UTF-8 -> French
// LANG=de_DE.UTF-8 -> German
```
## Frontend Usage (TypeScript)
```typescript
import {
SetLanguage,
Translate,
AvailableLanguages,
GetAllMessages
} from '@bindings/i18n/service';
// Set language
await SetLanguage("fr");
// Translate
const welcome = await Translate("welcome_message");
// Get available languages for a selector
const languages = await AvailableLanguages();
// Load all messages for client-side caching
const messages = await GetAllMessages("en");
```

View file

@ -1,76 +0,0 @@
# Installation
## Prerequisites
### Go 1.22+
```bash
# macOS
brew install go
# Linux
sudo apt install golang-go
# Windows - download from https://go.dev/dl/
```
### Wails v3
```bash
go install github.com/wailsapp/wails/v3/cmd/wails3@latest
```
### Task (Build Automation)
```bash
# macOS
brew install go-task
# Linux
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# Windows
choco install go-task
```
## Install Core
```bash
go get github.com/Snider/Core@latest
```
## Verify Installation
```bash
# Check Go
go version
# Check Wails
wails3 version
# Check Task
task --version
```
## IDE Setup
### VS Code
Install the Go extension and configure:
```json
{
"go.useLanguageServer": true,
"gopls": {
"ui.semanticTokens": true
}
}
```
### GoLand / IntelliJ
Go support is built-in. Enable the Wails plugin for additional features.
## Next Steps
Continue to [Quick Start](quickstart.md) to create your first application.

View file

@ -1,165 +0,0 @@
# IO Service
The IO package (`pkg/io`) provides a unified interface for file operations across different storage backends (local filesystem, S3, SFTP, etc.).
## Features
- Abstract `Medium` interface for storage backends
- Local filesystem implementation
- Copy between different mediums
- Mock implementation for testing
## Medium Interface
All storage backends implement the `Medium` interface:
```go
type Medium interface {
Read(path string) (string, error)
Write(path, content string) error
EnsureDir(path string) error
IsFile(path string) bool
FileGet(path string) (string, error)
FileSet(path, content string) error
}
```
## Local Filesystem
```go
import (
"github.com/Snider/Core/pkg/io"
"github.com/Snider/Core/pkg/io/local"
)
// Pre-initialized global medium (root = "/")
content, err := io.Local.Read("/etc/hosts")
// Create sandboxed medium
medium, err := local.New("/app/data")
content, err := medium.Read("config.json") // Reads /app/data/config.json
```
## Basic Operations
```go
// Read file
content, err := medium.Read("path/to/file.txt")
// Write file
err := medium.Write("path/to/file.txt", "content")
// Check if file exists
if medium.IsFile("config.json") {
// File exists
}
// Ensure directory exists
err := medium.EnsureDir("path/to/dir")
// Convenience methods
content, err := medium.FileGet("file.txt")
err := medium.FileSet("file.txt", "content")
```
## Helper Functions
Package-level functions that work with any Medium:
```go
// Read from medium
content, err := io.Read(medium, "file.txt")
// Write to medium
err := io.Write(medium, "file.txt", "content")
// Ensure directory
err := io.EnsureDir(medium, "path/to/dir")
// Check if file
exists := io.IsFile(medium, "file.txt")
```
## Copy Between Mediums
```go
localMedium, _ := local.New("/local/path")
remoteMedium := s3.New(bucket, region) // hypothetical S3 implementation
// Copy from local to remote
err := io.Copy(localMedium, "data.json", remoteMedium, "backup/data.json")
```
## Mock Medium for Testing
```go
import "github.com/Snider/Core/pkg/io"
func TestMyFunction(t *testing.T) {
mock := io.NewMockMedium()
// Pre-populate files
mock.Files["config.json"] = `{"key": "value"}`
mock.Dirs["data"] = true
// Use in tests
myService := NewService(mock)
// Verify writes
err := myService.SaveData("test")
if mock.Files["data/test.json"] != expectedContent {
t.Error("unexpected content")
}
}
```
## Creating Custom Backends
Implement the `Medium` interface for custom storage:
```go
type S3Medium struct {
bucket string
client *s3.Client
}
func (m *S3Medium) Read(path string) (string, error) {
// Implement S3 read
}
func (m *S3Medium) Write(path, content string) error {
// Implement S3 write
}
// ... implement remaining methods
```
## Error Handling
```go
content, err := medium.Read("missing.txt")
if err != nil {
// File not found or read error
log.Printf("Read failed: %v", err)
}
```
## Frontend Usage
The IO package is primarily used server-side. Frontend file operations should use the Display service dialogs or direct API calls:
```typescript
import { OpenFileDialog, SaveFileDialog } from '@bindings/display/service';
// Open file picker
const path = await OpenFileDialog({
title: "Select File",
filters: [{ displayName: "Text", pattern: "*.txt" }]
});
// Save file picker
const savePath = await SaveFileDialog({
title: "Save As",
defaultFilename: "document.txt"
});
```

View file

@ -1,119 +0,0 @@
# IPC & Actions
Core provides an inter-process communication system for services to communicate without tight coupling.
## Message Structure
```go
type Message struct {
Type string // Message type identifier
Data map[string]any // Message payload
Source string // Originating service (optional)
Timestamp time.Time // When message was created
}
```
## Sending Messages
```go
c.ACTION(core.Message{
Type: "user.created",
Data: map[string]any{
"id": "123",
"email": "user@example.com",
},
})
```
## Handling Messages
Register action handlers during service initialization:
```go
func NewNotificationService(c *core.Core) (any, error) {
svc := &NotificationService{}
// Register handler
c.RegisterAction(func(c *core.Core, msg core.Message) error {
return svc.handleAction(msg)
})
return svc, nil
}
func (s *NotificationService) handleAction(msg core.Message) error {
switch msg.Type {
case "user.created":
email := msg.Data["email"].(string)
return s.sendWelcomeEmail(email)
}
return nil
}
```
## Auto-Discovery
Services implementing `HandleIPCEvents` are automatically registered:
```go
type MyService struct{}
// Automatically registered when using WithService
func (s *MyService) HandleIPCEvents(c *core.Core, msg core.Message) error {
// Handle messages
return nil
}
```
## Common Patterns
### Request/Response
```go
// Sender
responseChan := make(chan any)
c.ACTION(core.Message{
Type: "data.request",
Data: map[string]any{
"query": "SELECT * FROM users",
"response": responseChan,
},
})
result := <-responseChan
// Handler
func (s *DataService) handleAction(msg core.Message) error {
if msg.Type == "data.request" {
query := msg.Data["query"].(string)
respChan := msg.Data["response"].(chan any)
result, err := s.execute(query)
if err != nil {
return err
}
respChan <- result
}
return nil
}
```
### Event Broadcasting
```go
// Broadcast to all listeners
c.ACTION(core.Message{
Type: "system.config.changed",
Data: map[string]any{
"key": "theme",
"value": "dark",
},
})
```
## Best Practices
1. **Use namespaced types** - `service.action` format
2. **Keep payloads simple** - Use primitive types when possible
3. **Handle errors** - Return errors from handlers
4. **Document message types** - Create constants for message types

View file

@ -1,101 +0,0 @@
# Service Lifecycle
Core provides lifecycle hooks for services to initialize and clean up resources.
## Lifecycle Interfaces
### Startable
Called when the application starts:
```go
type Startable interface {
OnStartup(ctx context.Context) error
}
```
### Stoppable
Called when the application shuts down:
```go
type Stoppable interface {
OnShutdown(ctx context.Context) error
}
```
## Implementation Example
```go
type DatabaseService struct {
db *sql.DB
}
func (s *DatabaseService) OnStartup(ctx context.Context) error {
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return err
}
// Verify connection
if err := db.PingContext(ctx); err != nil {
return err
}
s.db = db
return nil
}
func (s *DatabaseService) OnShutdown(ctx context.Context) error {
if s.db != nil {
return s.db.Close()
}
return nil
}
```
## Lifecycle Order
1. **Registration**: Services registered via `core.New()`
2. **Wails Binding**: Services bound to Wails app
3. **Startup**: `OnStartup()` called for each Startable service
4. **Running**: Application runs
5. **Shutdown**: `OnShutdown()` called for each Stoppable service
## Context Usage
The context passed to lifecycle methods includes:
- Cancellation signal for graceful shutdown
- Deadline for timeout handling
```go
func (s *Service) OnStartup(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-s.initialize():
return nil
}
}
```
## Error Handling
If `OnStartup` returns an error, the application will fail to start:
```go
func (s *Service) OnStartup(ctx context.Context) error {
if err := s.validate(); err != nil {
return fmt.Errorf("validation failed: %w", err)
}
return nil
}
```
## Best Practices
1. **Keep startup fast** - Defer heavy initialization
2. **Handle context cancellation** - Support graceful shutdown
3. **Clean up resources** - Always implement OnShutdown for services with resources
4. **Log lifecycle events** - Helps with debugging

View file

@ -1,220 +0,0 @@
# MCP Bridge
The MCP Bridge (`cmd/core-gui/mcp_bridge.go`) connects the Model Context Protocol server with Display, WebView, and WebSocket services.
## Overview
The MCP Bridge provides an HTTP API for AI assistants to interact with the desktop application, enabling:
- Window and screen management
- JavaScript execution in webviews
- DOM interaction (click, type, select)
- Screenshot capture
- File and process management
- Real-time events via WebSocket
## HTTP Endpoints
| Endpoint | Description |
|----------|-------------|
| `GET /health` | Health check |
| `GET /mcp` | Server capabilities |
| `GET /mcp/tools` | List available tools |
| `POST /mcp/call` | Execute a tool |
| `WS /ws` | WebSocket for GUI clients |
| `WS /events` | WebSocket for display events |
## Server Capabilities
```bash
curl http://localhost:9877/mcp
```
Response:
```json
{
"name": "core",
"version": "0.1.0",
"capabilities": {
"webview": true,
"display": true,
"windowControl": true,
"screenControl": true,
"websocket": "ws://localhost:9877/ws",
"events": "ws://localhost:9877/events"
}
}
```
## Tool Categories
### File Operations
| Tool | Description |
|------|-------------|
| `file_read` | Read file contents |
| `file_write` | Write content to file |
| `file_edit` | Edit file by replacing text |
| `file_delete` | Delete a file |
| `file_exists` | Check if file exists |
| `dir_list` | List directory contents |
| `dir_create` | Create directory |
### Window Control
| Tool | Description |
|------|-------------|
| `window_list` | List all windows |
| `window_create` | Create new window |
| `window_close` | Close window |
| `window_position` | Move window |
| `window_size` | Resize window |
| `window_maximize` | Maximize window |
| `window_minimize` | Minimize window |
| `window_focus` | Bring window to front |
### WebView Interaction
| Tool | Description |
|------|-------------|
| `webview_eval` | Execute JavaScript |
| `webview_click` | Click element |
| `webview_type` | Type into element |
| `webview_screenshot` | Capture page |
| `webview_navigate` | Navigate to URL |
| `webview_console` | Get console messages |
### Screen Management
| Tool | Description |
|------|-------------|
| `screen_list` | List all monitors |
| `screen_primary` | Get primary screen |
| `screen_at_point` | Get screen at coordinates |
| `screen_work_areas` | Get usable screen space |
### Layout Management
| Tool | Description |
|------|-------------|
| `layout_save` | Save window arrangement |
| `layout_restore` | Restore saved layout |
| `layout_tile` | Auto-tile windows |
| `layout_snap` | Snap window to edge |
## Calling Tools
```bash
# List windows
curl -X POST http://localhost:9877/mcp/call \
-H "Content-Type: application/json" \
-d '{"tool": "window_list", "params": {}}'
# Move window
curl -X POST http://localhost:9877/mcp/call \
-H "Content-Type: application/json" \
-d '{
"tool": "window_position",
"params": {"name": "main", "x": 100, "y": 100}
}'
# Execute JavaScript
curl -X POST http://localhost:9877/mcp/call \
-H "Content-Type: application/json" \
-d '{
"tool": "webview_eval",
"params": {
"window": "main",
"code": "document.title"
}
}'
# Click element
curl -X POST http://localhost:9877/mcp/call \
-H "Content-Type: application/json" \
-d '{
"tool": "webview_click",
"params": {
"window": "main",
"selector": "#submit-button"
}
}'
# Take screenshot
curl -X POST http://localhost:9877/mcp/call \
-H "Content-Type: application/json" \
-d '{
"tool": "webview_screenshot",
"params": {"window": "main"}
}'
```
## WebSocket Events
Connect to `/events` for real-time display events:
```javascript
const ws = new WebSocket('ws://localhost:9877/events');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'window.focus':
console.log('Window focused:', data.name);
break;
case 'window.move':
console.log('Window moved:', data.name, data.x, data.y);
break;
case 'theme.change':
console.log('Theme changed:', data.isDark);
break;
}
};
```
Event types:
- `window.focus` - Window received focus
- `window.blur` - Window lost focus
- `window.move` - Window position changed
- `window.resize` - Window size changed
- `window.close` - Window was closed
- `window.create` - New window created
- `theme.change` - System theme changed
- `screen.change` - Screen configuration changed
## Go Integration
```go
import "github.com/Snider/Core/cmd/core-gui"
// Create bridge
bridge := NewMCPBridge(9877, displayService)
// Access services
mcpSvc := bridge.GetMCPService()
webview := bridge.GetWebView()
display := bridge.GetDisplay()
```
## Configuration
The bridge starts automatically on Wails app startup via the `ServiceStartup` lifecycle hook:
```go
func (b *MCPBridge) ServiceStartup(ctx context.Context, options application.ServiceOptions) error {
b.app = application.Get()
b.webview.SetApp(b.app)
go b.startHTTPServer()
return nil
}
```
## Security
The MCP server binds to localhost only by default. For production:
- Consider firewall rules
- Add authentication if needed
- Limit exposed tools

Some files were not shown because too many files have changed in this diff Show more