docs: add examples for Go, PHP, and VM commands
This commit is contained in:
parent
55d4f0f385
commit
c1920e541e
120 changed files with 10254 additions and 5052 deletions
72
CLAUDE.md
72
CLAUDE.md
|
|
@ -5,11 +5,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
composer test # Run all tests
|
composer test # Run all tests (PHPUnit)
|
||||||
composer test -- --filter=Name # Run single test by name
|
composer test -- --filter=Name # Run single test by name
|
||||||
composer pint # Format code with Laravel Pint
|
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
|
## Architecture
|
||||||
|
|
||||||
### Event-Driven Module Loading
|
### Event-Driven Module Loading
|
||||||
|
|
@ -22,6 +32,8 @@ LifecycleEventProvider::register()
|
||||||
└── ModuleRegistry::register() # Wires LazyModuleListener for each event
|
└── 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
|
||||||
|
|
||||||
Frontages are ServiceProviders in `src/Core/Front/` that fire context-specific lifecycle events:
|
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 |
|
| Client | `ClientRoutesRegistering` | `client` | Authenticated SaaS |
|
||||||
| Cli | `ConsoleBooting` | - | Artisan commands |
|
| Cli | `ConsoleBooting` | - | Artisan commands |
|
||||||
| Mcp | `McpToolsRegistering` | - | MCP tool handlers |
|
| Mcp | `McpToolsRegistering` | - | MCP tool handlers |
|
||||||
|
| - | `FrameworkBooted` | - | Late-stage initialisation |
|
||||||
|
|
||||||
### L1 Packages
|
### L1 Packages
|
||||||
|
|
||||||
Subdirectories under `src/Core/` are self-contained "L1 packages" with their own Boot.php, migrations, tests, and views:
|
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/Bouncer/ # Security blocking/redirects
|
||||||
src/Core/Cdn/ # CDN integration
|
src/Core/Cdn/ # CDN integration
|
||||||
src/Core/Config/ # Dynamic configuration
|
src/Core/Config/ # Dynamic configuration
|
||||||
|
src/Core/Front/ # Frontage system (Web, Admin, Api, Client, Cli, Mcp)
|
||||||
src/Core/Lang/ # Translation system
|
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/Search/ # Search functionality
|
||||||
|
src/Core/Seo/ # SEO utilities
|
||||||
```
|
```
|
||||||
|
|
||||||
### Module Pattern
|
### Module Pattern
|
||||||
|
|
@ -63,6 +78,7 @@ class Boot
|
||||||
{
|
{
|
||||||
$event->views('example', __DIR__.'/Views');
|
$event->views('example', __DIR__.'/Views');
|
||||||
$event->routes(fn () => require __DIR__.'/Routes/web.php');
|
$event->routes(fn () => require __DIR__.'/Routes/web.php');
|
||||||
|
$event->livewire('example.widget', ExampleWidget::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -88,20 +104,62 @@ class CreateOrder
|
||||||
{
|
{
|
||||||
use Action;
|
use Action;
|
||||||
|
|
||||||
|
public function __construct(private OrderService $orders) {}
|
||||||
|
|
||||||
public function handle(User $user, array $data): Order
|
public function handle(User $user, array $data): Order
|
||||||
{
|
{
|
||||||
return Order::create($data);
|
return $this->orders->create($user, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage: CreateOrder::run($user, $validated);
|
// 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
|
## 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
|
- `tests/Feature/` and `tests/Unit/` - main test suites
|
||||||
- `src/Core/{Package}/Tests/` - L1 package co-located tests
|
- `src/Core/{Package}/Tests/` - L1 package co-located tests
|
||||||
- `src/Mod/{Module}/Tests/` - module co-located tests
|
- `src/Mod/{Module}/Tests/` - module co-located tests
|
||||||
|
|
||||||
Test fixtures are in `tests/Fixtures/`.
|
Test fixtures are in `tests/Fixtures/`.
|
||||||
|
|
||||||
|
Base test class provides:
|
||||||
|
```php
|
||||||
|
$this->getFixturePath('Mod') // Returns tests/Fixtures/Mod path
|
||||||
|
```
|
||||||
|
|
|
||||||
402
docs/packages/commerce/architecture.md
Normal file
402
docs/packages/commerce/architecture.md
Normal 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
|
||||||
327
docs/packages/commerce/security.md
Normal file
327
docs/packages/commerce/security.md
Normal 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.
|
||||||
387
docs/packages/commerce/webhooks.md
Normal file
387
docs/packages/commerce/webhooks.md
Normal 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;
|
||||||
|
```
|
||||||
422
docs/packages/content/architecture.md
Normal file
422
docs/packages/content/architecture.md
Normal 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()`
|
||||||
389
docs/packages/content/security.md
Normal file
389
docs/packages/content/security.md
Normal 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.
|
||||||
390
docs/packages/developer/architecture.md
Normal file
390
docs/packages/developer/architecture.md
Normal 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.
|
||||||
269
docs/packages/developer/security.md
Normal file
269
docs/packages/developer/security.md
Normal 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
|
||||||
100
docs/packages/go/cmd/ai/example.md
Normal file
100
docs/packages/go/cmd/ai/example.md
Normal 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
|
||||||
|
```
|
||||||
262
docs/packages/go/cmd/ai/index.md
Normal file
262
docs/packages/go/cmd/ai/index.md
Normal 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)
|
||||||
83
docs/packages/go/cmd/build/example.md
Normal file
83
docs/packages/go/cmd/build/example.md
Normal 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
|
||||||
|
```
|
||||||
|
|
@ -2,6 +2,14 @@
|
||||||
|
|
||||||
Build Go, Wails, Docker, and LinuxKit projects with automatic project detection.
|
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
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -12,12 +20,17 @@ core build [flags]
|
||||||
|
|
||||||
| Flag | Description |
|
| 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` |
|
| `--targets` | Build targets: `linux/amd64,darwin/arm64,windows/amd64` |
|
||||||
| `--output` | Output directory (default: `dist`) |
|
| `--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) |
|
| `--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) |
|
| `--notarize` | Enable macOS notarization (requires Apple credentials) |
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
@ -53,6 +66,9 @@ core build --type docker
|
||||||
|
|
||||||
# With custom image name
|
# With custom image name
|
||||||
core build --type docker --image ghcr.io/myorg/myapp
|
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
|
### LinuxKit Image
|
||||||
|
|
@ -60,6 +76,9 @@ core build --type docker --image ghcr.io/myorg/myapp
|
||||||
```bash
|
```bash
|
||||||
# Build LinuxKit ISO
|
# Build LinuxKit ISO
|
||||||
core build --type linuxkit
|
core build --type linuxkit
|
||||||
|
|
||||||
|
# Build with specific format
|
||||||
|
core build --type linuxkit --config linuxkit.yml --format qcow2-bios
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Detection
|
## Project Detection
|
||||||
|
|
@ -71,6 +90,7 @@ Core automatically detects project type based on files:
|
||||||
| `wails.json` | Wails |
|
| `wails.json` | Wails |
|
||||||
| `go.mod` | Go |
|
| `go.mod` | Go |
|
||||||
| `Dockerfile` | Docker |
|
| `Dockerfile` | Docker |
|
||||||
|
| `Taskfile.yml` | Taskfile |
|
||||||
| `composer.json` | PHP |
|
| `composer.json` | PHP |
|
||||||
| `package.json` | Node |
|
| `package.json` | Node |
|
||||||
|
|
||||||
|
|
@ -90,40 +110,7 @@ dist/
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Optional `.core/build.yaml`:
|
Optional `.core/build.yaml` - see [Configuration](example.md#configuration) for examples.
|
||||||
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Signing
|
## Code Signing
|
||||||
|
|
||||||
|
|
@ -169,3 +156,21 @@ core build --notarize
|
||||||
| `APPLE_ID` | Apple account email |
|
| `APPLE_ID` | Apple account email |
|
||||||
| `APPLE_TEAM_ID` | Apple Developer Team ID |
|
| `APPLE_TEAM_ID` | Apple Developer Team ID |
|
||||||
| `APPLE_APP_PASSWORD` | App-specific password for notarization |
|
| `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
|
||||||
|
```
|
||||||
56
docs/packages/go/cmd/build/sdk/example.md
Normal file
56
docs/packages/go/cmd/build/sdk/example.md
Normal 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
|
||||||
|
```
|
||||||
27
docs/packages/go/cmd/build/sdk/index.md
Normal file
27
docs/packages/go/cmd/build/sdk/index.md
Normal 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
|
||||||
|
```
|
||||||
36
docs/packages/go/cmd/ci/changelog/example.md
Normal file
36
docs/packages/go/cmd/ci/changelog/example.md
Normal 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
|
||||||
|
```
|
||||||
28
docs/packages/go/cmd/ci/changelog/index.md
Normal file
28
docs/packages/go/cmd/ci/changelog/index.md
Normal 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.
|
||||||
90
docs/packages/go/cmd/ci/example.md
Normal file
90
docs/packages/go/cmd/ci/example.md
Normal 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
|
||||||
|
```
|
||||||
79
docs/packages/go/cmd/ci/index.md
Normal file
79
docs/packages/go/cmd/ci/index.md
Normal 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).
|
||||||
17
docs/packages/go/cmd/ci/init/example.md
Normal file
17
docs/packages/go/cmd/ci/init/example.md
Normal 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
|
||||||
|
```
|
||||||
11
docs/packages/go/cmd/ci/init/index.md
Normal file
11
docs/packages/go/cmd/ci/init/index.md
Normal 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.
|
||||||
18
docs/packages/go/cmd/ci/version/example.md
Normal file
18
docs/packages/go/cmd/ci/version/example.md
Normal 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)
|
||||||
21
docs/packages/go/cmd/ci/version/index.md
Normal file
21
docs/packages/go/cmd/ci/version/index.md
Normal 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)
|
||||||
61
docs/packages/go/cmd/dev/ci/index.md
Normal file
61
docs/packages/go/cmd/dev/ci/index.md
Normal 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
|
||||||
46
docs/packages/go/cmd/dev/commit/index.md
Normal file
46
docs/packages/go/cmd/dev/commit/index.md
Normal 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)
|
||||||
203
docs/packages/go/cmd/dev/example.md
Normal file
203
docs/packages/go/cmd/dev/example.md
Normal 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
|
||||||
|
```
|
||||||
52
docs/packages/go/cmd/dev/health/index.md
Normal file
52
docs/packages/go/cmd/dev/health/index.md
Normal 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
|
||||||
65
docs/packages/go/cmd/dev/impact/index.md
Normal file
65
docs/packages/go/cmd/dev/impact/index.md
Normal 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
|
||||||
|
|
@ -1,24 +1,55 @@
|
||||||
# core dev
|
# core dev
|
||||||
|
|
||||||
Portable development environment with 100+ embedded tools.
|
Multi-repo workflow and portable development environment.
|
||||||
|
|
||||||
## Overview
|
## Multi-Repo Commands
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `install` | Download the core-devops image for your platform |
|
| [work](work/) | Full workflow: status + commit + push |
|
||||||
| `boot` | Start the development environment |
|
| `health` | Quick health check across repos |
|
||||||
| `stop` | Stop the running environment |
|
| `commit` | Claude-assisted commits |
|
||||||
| `status` | Show environment status |
|
| `push` | Push repos with unpushed commits |
|
||||||
| `shell` | Open a shell in the environment |
|
| `pull` | Pull repos that are behind |
|
||||||
| `serve` | Mount project and start dev server |
|
| `issues` | List open issues |
|
||||||
| `test` | Run tests inside the environment |
|
| `reviews` | List PRs needing review |
|
||||||
| `claude` | Start sandboxed Claude session |
|
| `ci` | Check CI status |
|
||||||
| `update` | Update to latest image |
|
| `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
|
## Quick Start
|
||||||
|
|
||||||
|
|
@ -39,24 +70,16 @@ core dev serve
|
||||||
Download the core-devops image for your platform.
|
Download the core-devops image for your platform.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core dev install [flags]
|
core dev install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flags
|
Downloads the platform-specific dev environment image including Go, PHP, Node.js, Python, Docker, and Claude CLI. Downloads are cached at `~/.core/images/`.
|
||||||
|
|
||||||
| Flag | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `--source` | Image source: `github`, `registry`, `cdn` (default: auto) |
|
|
||||||
| `--force` | Force re-download even if exists |
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Download image (auto-detects platform)
|
# Download image (auto-detects platform)
|
||||||
core dev install
|
core dev install
|
||||||
|
|
||||||
# Force re-download
|
|
||||||
core dev install --force
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## dev boot
|
## dev boot
|
||||||
|
|
@ -72,8 +95,8 @@ core dev boot [flags]
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `--memory` | Memory allocation in MB (default: 4096) |
|
| `--memory` | Memory allocation in MB (default: 4096) |
|
||||||
| `--cpus` | Number of CPUs (default: 4) |
|
| `--cpus` | Number of CPUs (default: 2) |
|
||||||
| `--name` | Container name (default: core-dev) |
|
| `--fresh` | Stop existing and start fresh |
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
|
@ -82,7 +105,10 @@ core dev boot [flags]
|
||||||
core dev boot
|
core dev boot
|
||||||
|
|
||||||
# More resources
|
# More resources
|
||||||
core dev boot --memory 8192 --cpus 8
|
core dev boot --memory 8192 --cpus 4
|
||||||
|
|
||||||
|
# Fresh start
|
||||||
|
core dev boot --fresh
|
||||||
```
|
```
|
||||||
|
|
||||||
## dev shell
|
## dev shell
|
||||||
|
|
@ -90,9 +116,11 @@ core dev boot --memory 8192 --cpus 8
|
||||||
Open a shell in the running environment.
|
Open a shell in the running environment.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core dev shell [flags]
|
core dev shell [flags] [-- command]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Uses SSH by default, or serial console with `--console`.
|
||||||
|
|
||||||
### Flags
|
### Flags
|
||||||
|
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|
|
@ -107,6 +135,9 @@ core dev shell
|
||||||
|
|
||||||
# Serial console (for debugging)
|
# Serial console (for debugging)
|
||||||
core dev shell --console
|
core dev shell --console
|
||||||
|
|
||||||
|
# Run a command
|
||||||
|
core dev shell -- ls -la
|
||||||
```
|
```
|
||||||
|
|
||||||
## dev serve
|
## dev serve
|
||||||
|
|
@ -155,11 +186,11 @@ core dev test [flags] [-- custom command]
|
||||||
|
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `--unit` | Run only unit tests |
|
| `--name` | Run named test command from `.core/test.yaml` |
|
||||||
|
|
||||||
### Test Detection
|
### 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
|
1. `.core/test.yaml` - Custom config
|
||||||
2. `composer.json` → `composer test`
|
2. `composer.json` → `composer test`
|
||||||
|
|
@ -174,29 +205,16 @@ Core auto-detects the test framework:
|
||||||
# Auto-detect and run tests
|
# Auto-detect and run tests
|
||||||
core dev test
|
core dev test
|
||||||
|
|
||||||
|
# Run named test from config
|
||||||
|
core dev test --name integration
|
||||||
|
|
||||||
# Custom command
|
# Custom command
|
||||||
core dev test -- go test -v ./pkg/...
|
core dev test -- go test -v ./pkg/...
|
||||||
```
|
```
|
||||||
|
|
||||||
### Test Configuration
|
### Test Configuration
|
||||||
|
|
||||||
Create `.core/test.yaml` for custom test setup:
|
Create `.core/test.yaml` for custom test setup - see [Configuration](example.md#configuration) for examples.
|
||||||
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
## dev claude
|
## dev claude
|
||||||
|
|
||||||
|
|
@ -210,8 +228,9 @@ core dev claude [flags]
|
||||||
|
|
||||||
| Flag | Description |
|
| Flag | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `--no-auth` | Clean session without host credentials |
|
| `--model` | Model to use (`opus`, `sonnet`) |
|
||||||
| `--auth` | Selective auth forwarding (e.g., `gh,anthropic`) |
|
| `--no-auth` | Don't forward any auth credentials |
|
||||||
|
| `--auth` | Selective auth forwarding (`gh`, `anthropic`, `ssh`, `git`) |
|
||||||
|
|
||||||
### What Gets Forwarded
|
### What Gets Forwarded
|
||||||
|
|
||||||
|
|
@ -227,11 +246,14 @@ By default, these are forwarded to the sandbox:
|
||||||
# Full auth forwarding (default)
|
# Full auth forwarding (default)
|
||||||
core dev claude
|
core dev claude
|
||||||
|
|
||||||
|
# Use Opus model
|
||||||
|
core dev claude --model opus
|
||||||
|
|
||||||
# Clean sandbox
|
# Clean sandbox
|
||||||
core dev claude --no-auth
|
core dev claude --no-auth
|
||||||
|
|
||||||
# Only GitHub auth
|
# Only GitHub and Anthropic auth
|
||||||
core dev claude --auth=gh
|
core dev claude --auth gh,anthropic
|
||||||
```
|
```
|
||||||
|
|
||||||
### Why Use This?
|
### Why Use This?
|
||||||
|
|
@ -258,7 +280,7 @@ Output includes:
|
||||||
|
|
||||||
## dev update
|
## dev update
|
||||||
|
|
||||||
Check for and download newer images.
|
Check for and apply updates.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core dev update [flags]
|
core dev update [flags]
|
||||||
|
|
@ -268,7 +290,17 @@ core dev update [flags]
|
||||||
|
|
||||||
| Flag | Description |
|
| 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
|
## Embedded Tools
|
||||||
|
|
||||||
|
|
@ -293,23 +325,7 @@ The core-devops image includes 100+ tools:
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Global config in `~/.core/config.yaml`:
|
Global config in `~/.core/config.yaml` - see [Configuration](example.md#configuration) for examples.
|
||||||
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
## Image Storage
|
## Image Storage
|
||||||
|
|
||||||
|
|
@ -323,3 +339,50 @@ Images are stored in `~/.core/images/`:
|
||||||
├── core-devops-linux-amd64.qcow2
|
├── core-devops-linux-amd64.qcow2
|
||||||
└── manifest.json
|
└── 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.)
|
||||||
57
docs/packages/go/cmd/dev/issues/index.md
Normal file
57
docs/packages/go/cmd/dev/issues/index.md
Normal 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
|
||||||
47
docs/packages/go/cmd/dev/pull/index.md
Normal file
47
docs/packages/go/cmd/dev/pull/index.md
Normal 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
|
||||||
52
docs/packages/go/cmd/dev/push/index.md
Normal file
52
docs/packages/go/cmd/dev/push/index.md
Normal 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)
|
||||||
61
docs/packages/go/cmd/dev/reviews/index.md
Normal file
61
docs/packages/go/cmd/dev/reviews/index.md
Normal 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
|
||||||
33
docs/packages/go/cmd/dev/work/example.md
Normal file
33
docs/packages/go/cmd/dev/work/example.md
Normal 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
|
||||||
|
```
|
||||||
293
docs/packages/go/cmd/dev/work/index.md
Normal file
293
docs/packages/go/cmd/dev/work/index.md
Normal 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
|
||||||
14
docs/packages/go/cmd/docs/example.md
Normal file
14
docs/packages/go/cmd/docs/example.md
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Docs Examples
|
||||||
|
|
||||||
|
## List
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core docs list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sync
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core docs sync
|
||||||
|
core docs sync --output ./docs
|
||||||
|
```
|
||||||
|
|
@ -107,4 +107,4 @@ The synced docs are used to build https://core.help:
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [Configuration](../configuration.md) - Project configuration
|
- [Configuration](../../configuration.md) - Project configuration
|
||||||
20
docs/packages/go/cmd/doctor/example.md
Normal file
20
docs/packages/go/cmd/doctor/example.md
Normal 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
|
||||||
|
```
|
||||||
|
|
@ -5,9 +5,15 @@ Check your development environment for required tools and configuration.
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core doctor
|
core doctor [flags]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Flags
|
||||||
|
|
||||||
|
| Flag | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| `--verbose` | Show detailed version information |
|
||||||
|
|
||||||
## What It Checks
|
## What It Checks
|
||||||
|
|
||||||
### Required Tools
|
### Required Tools
|
||||||
|
|
@ -71,5 +77,5 @@ All checks passed!
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [setup command](setup.md) - Clone repos from registry
|
- [setup command](../setup/) - Clone repos from registry
|
||||||
- [dev install](dev.md) - Install development environment
|
- [dev](../dev/) - Development environment
|
||||||
18
docs/packages/go/cmd/go/cov/example.md
Normal file
18
docs/packages/go/cmd/go/cov/example.md
Normal 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
|
||||||
|
```
|
||||||
28
docs/packages/go/cmd/go/cov/index.md
Normal file
28
docs/packages/go/cmd/go/cov/index.md
Normal 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
|
||||||
|
```
|
||||||
89
docs/packages/go/cmd/go/example.md
Normal file
89
docs/packages/go/cmd/go/example.md
Normal 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
|
||||||
|
```
|
||||||
12
docs/packages/go/cmd/go/fmt/example.md
Normal file
12
docs/packages/go/cmd/go/fmt/example.md
Normal 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
|
||||||
|
```
|
||||||
25
docs/packages/go/cmd/go/fmt/index.md
Normal file
25
docs/packages/go/cmd/go/fmt/index.md
Normal 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
|
||||||
|
```
|
||||||
15
docs/packages/go/cmd/go/index.md
Normal file
15
docs/packages/go/cmd/go/index.md
Normal 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 |
|
||||||
15
docs/packages/go/cmd/go/install/example.md
Normal file
15
docs/packages/go/cmd/go/install/example.md
Normal 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
|
||||||
|
```
|
||||||
25
docs/packages/go/cmd/go/install/index.md
Normal file
25
docs/packages/go/cmd/go/install/index.md
Normal 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
|
||||||
|
```
|
||||||
22
docs/packages/go/cmd/go/lint/example.md
Normal file
22
docs/packages/go/cmd/go/lint/example.md
Normal 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
|
||||||
|
```
|
||||||
22
docs/packages/go/cmd/go/lint/index.md
Normal file
22
docs/packages/go/cmd/go/lint/index.md
Normal 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
|
||||||
|
```
|
||||||
29
docs/packages/go/cmd/go/mod/download/index.md
Normal file
29
docs/packages/go/cmd/go/mod/download/index.md
Normal 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
|
||||||
15
docs/packages/go/cmd/go/mod/example.md
Normal file
15
docs/packages/go/cmd/go/mod/example.md
Normal 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
|
||||||
|
```
|
||||||
44
docs/packages/go/cmd/go/mod/graph/index.md
Normal file
44
docs/packages/go/cmd/go/mod/graph/index.md
Normal 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
|
||||||
21
docs/packages/go/cmd/go/mod/index.md
Normal file
21
docs/packages/go/cmd/go/mod/index.md
Normal 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
|
||||||
|
```
|
||||||
29
docs/packages/go/cmd/go/mod/tidy/index.md
Normal file
29
docs/packages/go/cmd/go/mod/tidy/index.md
Normal 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
|
||||||
41
docs/packages/go/cmd/go/mod/verify/index.md
Normal file
41
docs/packages/go/cmd/go/mod/verify/index.md
Normal 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
|
||||||
27
docs/packages/go/cmd/go/test/example.md
Normal file
27
docs/packages/go/cmd/go/test/example.md
Normal 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
|
||||||
|
```
|
||||||
31
docs/packages/go/cmd/go/test/index.md
Normal file
31
docs/packages/go/cmd/go/test/index.md
Normal 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
|
||||||
|
```
|
||||||
19
docs/packages/go/cmd/go/work/index.md
Normal file
19
docs/packages/go/cmd/go/work/index.md
Normal 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
|
||||||
|
```
|
||||||
40
docs/packages/go/cmd/go/work/init/index.md
Normal file
40
docs/packages/go/cmd/go/work/init/index.md
Normal 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
|
||||||
35
docs/packages/go/cmd/go/work/sync/index.md
Normal file
35
docs/packages/go/cmd/go/work/sync/index.md
Normal 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
|
||||||
46
docs/packages/go/cmd/go/work/use/index.md
Normal file
46
docs/packages/go/cmd/go/work/use/index.md
Normal 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
|
||||||
31
docs/packages/go/cmd/index.md
Normal file
31
docs/packages/go/cmd/index.md
Normal 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.
|
||||||
|
|
@ -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
|
|
||||||
```
|
|
||||||
111
docs/packages/go/cmd/php/example.md
Normal file
111
docs/packages/go/cmd/php/example.md
Normal 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
|
||||||
|
```
|
||||||
413
docs/packages/go/cmd/php/index.md
Normal file
413
docs/packages/go/cmd/php/index.md
Normal 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.
|
||||||
36
docs/packages/go/cmd/pkg/example.md
Normal file
36
docs/packages/go/cmd/pkg/example.md
Normal 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
|
||||||
|
```
|
||||||
144
docs/packages/go/cmd/pkg/index.md
Normal file
144
docs/packages/go/cmd/pkg/index.md
Normal 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
|
||||||
23
docs/packages/go/cmd/pkg/search/example.md
Normal file
23
docs/packages/go/cmd/pkg/search/example.md
Normal 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 │
|
||||||
|
└──────────────┴─────────────────────────────┘
|
||||||
|
```
|
||||||
75
docs/packages/go/cmd/pkg/search/index.md
Normal file
75
docs/packages/go/cmd/pkg/search/index.md
Normal 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
|
||||||
|
|
@ -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
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
```
|
|
||||||
35
docs/packages/go/cmd/sdk/example.md
Normal file
35
docs/packages/go/cmd/sdk/example.md
Normal 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
|
||||||
|
```
|
||||||
106
docs/packages/go/cmd/sdk/index.md
Normal file
106
docs/packages/go/cmd/sdk/index.md
Normal 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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
293
docs/packages/go/cmd/setup/example.md
Normal file
293
docs/packages/go/cmd/setup/example.md
Normal 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
|
||||||
|
```
|
||||||
213
docs/packages/go/cmd/setup/index.md
Normal file
213
docs/packages/go/cmd/setup/index.md
Normal 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
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
8
docs/packages/go/cmd/test/example.md
Normal file
8
docs/packages/go/cmd/test/example.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Test Examples
|
||||||
|
|
||||||
|
**Note:** Prefer `core go test` or `core php test` instead.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
core test
|
||||||
|
core test --coverage
|
||||||
|
```
|
||||||
74
docs/packages/go/cmd/test/index.md
Normal file
74
docs/packages/go/cmd/test/index.md
Normal 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
|
||||||
52
docs/packages/go/cmd/vm/example.md
Normal file
52
docs/packages/go/cmd/vm/example.md
Normal 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
|
||||||
|
```
|
||||||
163
docs/packages/go/cmd/vm/index.md
Normal file
163
docs/packages/go/cmd/vm/index.md
Normal 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
|
||||||
53
docs/packages/go/cmd/vm/templates/example.md
Normal file
53
docs/packages/go/cmd/vm/templates/example.md
Normal 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
|
||||||
|
```
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# core templates
|
# core vm templates
|
||||||
|
|
||||||
Manage LinuxKit templates for container images.
|
Manage LinuxKit templates for container images.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core templates [command]
|
core vm templates [command]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
@ -14,13 +14,14 @@ core templates [command]
|
||||||
|---------|-------------|
|
|---------|-------------|
|
||||||
| `list` | List available templates |
|
| `list` | List available templates |
|
||||||
| `show` | Show template details |
|
| `show` | Show template details |
|
||||||
|
| `vars` | Show template variables |
|
||||||
|
|
||||||
## templates list
|
## templates list
|
||||||
|
|
||||||
List all available LinuxKit templates.
|
List all available LinuxKit templates.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core templates list
|
core vm templates list
|
||||||
```
|
```
|
||||||
|
|
||||||
### Output
|
### Output
|
||||||
|
|
@ -46,13 +47,13 @@ Available Templates:
|
||||||
Show details of a specific template.
|
Show details of a specific template.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core templates show <name>
|
core vm templates show <name>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core templates show core-dev
|
core vm templates show core-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Output:
|
Output:
|
||||||
|
|
@ -77,6 +78,28 @@ Services:
|
||||||
Size: ~1.8GB
|
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
|
## Template Locations
|
||||||
|
|
||||||
Templates are searched in order:
|
Templates are searched in order:
|
||||||
|
|
@ -87,31 +110,15 @@ Templates are searched in order:
|
||||||
|
|
||||||
## Creating Templates
|
## Creating Templates
|
||||||
|
|
||||||
Create a LinuxKit YAML in `.core/linuxkit/`:
|
Create a LinuxKit YAML in `.core/linuxkit/`. See [Template Format](example.md#template-format) for examples.
|
||||||
|
|
||||||
```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
|
|
||||||
```
|
|
||||||
|
|
||||||
Run with:
|
Run with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
core run --template myserver
|
core vm run --template myserver
|
||||||
```
|
```
|
||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- [run command](run.md) - Run LinuxKit images
|
- [vm command](../) - Run LinuxKit images
|
||||||
- [build command](build.md) - Build LinuxKit images
|
- [build command](../../build/) - Build LinuxKit images
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -205,14 +205,148 @@ files:
|
||||||
port: 8080
|
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
|
## 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 |
|
| Variable | Description |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
| `GITHUB_TOKEN` | GitHub authentication (via gh CLI) |
|
| `CORE_CONFIG` | Override config directory (default: `~/.core/`) |
|
||||||
| `NPM_TOKEN` | npm publish token |
|
| `CORE_REGISTRY` | Override repos.yaml path |
|
||||||
| `CHOCOLATEY_API_KEY` | Chocolatey publish key |
|
|
||||||
| `COOLIFY_TOKEN` | Coolify deployment token |
|
---
|
||||||
|
|
||||||
## Defaults
|
## Defaults
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -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);
|
|
||||||
```
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
@ -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");
|
|
||||||
```
|
|
||||||
|
|
@ -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.
|
|
||||||
|
|
@ -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"
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
Loading…
Add table
Reference in a new issue