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
68
CLAUDE.md
68
CLAUDE.md
|
|
@ -5,11 +5,21 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
## Commands
|
||||
|
||||
```bash
|
||||
composer test # Run all tests
|
||||
composer test # Run all tests (PHPUnit)
|
||||
composer test -- --filter=Name # Run single test by name
|
||||
composer test -- --testsuite=Unit # Run specific test suite
|
||||
composer pint # Format code with Laravel Pint
|
||||
./vendor/bin/pint --dirty # Format only changed files
|
||||
```
|
||||
|
||||
## Coding Standards
|
||||
|
||||
- **UK English**: colour, organisation, centre (never American spellings)
|
||||
- **Strict types**: `declare(strict_types=1);` in every PHP file
|
||||
- **Type hints**: All parameters and return types required
|
||||
- **Testing**: PHPUnit with Orchestra Testbench
|
||||
- **License**: EUPL-1.2
|
||||
|
||||
## Architecture
|
||||
|
||||
### Event-Driven Module Loading
|
||||
|
|
@ -22,6 +32,8 @@ LifecycleEventProvider::register()
|
|||
└── ModuleRegistry::register() # Wires LazyModuleListener for each event
|
||||
```
|
||||
|
||||
**Key benefit**: Web requests don't load admin modules; API requests don't load web modules.
|
||||
|
||||
### Frontages
|
||||
|
||||
Frontages are ServiceProviders in `src/Core/Front/` that fire context-specific lifecycle events:
|
||||
|
|
@ -34,19 +46,22 @@ Frontages are ServiceProviders in `src/Core/Front/` that fire context-specific l
|
|||
| Client | `ClientRoutesRegistering` | `client` | Authenticated SaaS |
|
||||
| Cli | `ConsoleBooting` | - | Artisan commands |
|
||||
| Mcp | `McpToolsRegistering` | - | MCP tool handlers |
|
||||
| - | `FrameworkBooted` | - | Late-stage initialisation |
|
||||
|
||||
### L1 Packages
|
||||
|
||||
Subdirectories under `src/Core/` are self-contained "L1 packages" with their own Boot.php, migrations, tests, and views:
|
||||
|
||||
```
|
||||
src/Core/Activity/ # Activity logging
|
||||
src/Core/Activity/ # Activity logging (wraps spatie/laravel-activitylog)
|
||||
src/Core/Bouncer/ # Security blocking/redirects
|
||||
src/Core/Cdn/ # CDN integration
|
||||
src/Core/Config/ # Dynamic configuration
|
||||
src/Core/Front/ # Frontage system (Web, Admin, Api, Client, Cli, Mcp)
|
||||
src/Core/Lang/ # Translation system
|
||||
src/Core/Media/ # Media handling
|
||||
src/Core/Media/ # Media handling with thumbnail helpers
|
||||
src/Core/Search/ # Search functionality
|
||||
src/Core/Seo/ # SEO utilities
|
||||
```
|
||||
|
||||
### Module Pattern
|
||||
|
|
@ -63,6 +78,7 @@ class Boot
|
|||
{
|
||||
$event->views('example', __DIR__.'/Views');
|
||||
$event->routes(fn () => require __DIR__.'/Routes/web.php');
|
||||
$event->livewire('example.widget', ExampleWidget::class);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -88,20 +104,62 @@ class CreateOrder
|
|||
{
|
||||
use Action;
|
||||
|
||||
public function __construct(private OrderService $orders) {}
|
||||
|
||||
public function handle(User $user, array $data): Order
|
||||
{
|
||||
return Order::create($data);
|
||||
return $this->orders->create($user, $data);
|
||||
}
|
||||
}
|
||||
|
||||
// Usage: CreateOrder::run($user, $validated);
|
||||
```
|
||||
|
||||
### Seeder Ordering
|
||||
|
||||
Seeders use PHP attributes for dependency ordering:
|
||||
|
||||
```php
|
||||
use Core\Database\Seeders\Attributes\SeederPriority;
|
||||
use Core\Database\Seeders\Attributes\SeederAfter;
|
||||
|
||||
#[SeederPriority(50)] // Lower runs first (default 50)
|
||||
#[SeederAfter(FeatureSeeder::class)]
|
||||
class PackageSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
if (! Schema::hasTable('packages')) return; // Guard missing tables
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### HLCRF Layout System
|
||||
|
||||
Data-driven layouts with five regions (Header, Left, Content, Right, Footer):
|
||||
|
||||
```php
|
||||
use Core\Front\Components\Layout;
|
||||
|
||||
$page = Layout::make('HCF') // Variant: Header-Content-Footer
|
||||
->h(view('header'))
|
||||
->c($content)
|
||||
->f(view('footer'));
|
||||
```
|
||||
|
||||
Variant strings: `C` (content only), `HCF` (standard page), `HLCF` (with sidebar), `HLCRF` (full dashboard).
|
||||
|
||||
## Testing
|
||||
|
||||
Uses Orchestra Testbench. Tests can live:
|
||||
Uses Orchestra Testbench with in-memory SQLite. Tests can live:
|
||||
- `tests/Feature/` and `tests/Unit/` - main test suites
|
||||
- `src/Core/{Package}/Tests/` - L1 package co-located tests
|
||||
- `src/Mod/{Module}/Tests/` - module co-located tests
|
||||
|
||||
Test fixtures are in `tests/Fixtures/`.
|
||||
|
||||
Base test class provides:
|
||||
```php
|
||||
$this->getFixturePath('Mod') // Returns tests/Fixtures/Mod path
|
||||
```
|
||||
|
|
|
|||
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.
|
||||
|
||||
## Subcommands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [sdk](sdk/) | Generate API SDKs from OpenAPI |
|
||||
| `from-path` | Build from a local directory |
|
||||
| `pwa` | Build from a live PWA URL |
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
|
|
@ -12,12 +20,17 @@ core build [flags]
|
|||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--type` | Project type: `go`, `wails`, `docker`, `linuxkit` (auto-detected) |
|
||||
| `--type` | Project type: `go`, `wails`, `docker`, `linuxkit`, `taskfile` (auto-detected) |
|
||||
| `--targets` | Build targets: `linux/amd64,darwin/arm64,windows/amd64` |
|
||||
| `--output` | Output directory (default: `dist`) |
|
||||
| `--ci` | CI mode - non-interactive, fail fast |
|
||||
| `--ci` | CI mode - minimal output with JSON artifact list at the end |
|
||||
| `--image` | Docker image name (for docker builds) |
|
||||
| `--no-sign` | Skip code signing |
|
||||
| `--config` | Config file path (for linuxkit: YAML config, for docker: Dockerfile) |
|
||||
| `--format` | Output format for linuxkit (iso-bios, qcow2-bios, raw, vmdk) |
|
||||
| `--push` | Push Docker image after build (default: false) |
|
||||
| `--archive` | Create archives (tar.gz for linux/darwin, zip for windows) - default: true |
|
||||
| `--checksum` | Generate SHA256 checksums and CHECKSUMS.txt - default: true |
|
||||
| `--no-sign` | Skip all code signing |
|
||||
| `--notarize` | Enable macOS notarization (requires Apple credentials) |
|
||||
|
||||
## Examples
|
||||
|
|
@ -53,6 +66,9 @@ core build --type docker
|
|||
|
||||
# With custom image name
|
||||
core build --type docker --image ghcr.io/myorg/myapp
|
||||
|
||||
# Build and push to registry
|
||||
core build --type docker --image ghcr.io/myorg/myapp --push
|
||||
```
|
||||
|
||||
### LinuxKit Image
|
||||
|
|
@ -60,6 +76,9 @@ core build --type docker --image ghcr.io/myorg/myapp
|
|||
```bash
|
||||
# Build LinuxKit ISO
|
||||
core build --type linuxkit
|
||||
|
||||
# Build with specific format
|
||||
core build --type linuxkit --config linuxkit.yml --format qcow2-bios
|
||||
```
|
||||
|
||||
## Project Detection
|
||||
|
|
@ -71,6 +90,7 @@ Core automatically detects project type based on files:
|
|||
| `wails.json` | Wails |
|
||||
| `go.mod` | Go |
|
||||
| `Dockerfile` | Docker |
|
||||
| `Taskfile.yml` | Taskfile |
|
||||
| `composer.json` | PHP |
|
||||
| `package.json` | Node |
|
||||
|
||||
|
|
@ -90,40 +110,7 @@ dist/
|
|||
|
||||
## Configuration
|
||||
|
||||
Optional `.core/build.yaml`:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
|
||||
project:
|
||||
name: myapp
|
||||
binary: myapp
|
||||
|
||||
build:
|
||||
main: ./cmd/myapp
|
||||
ldflags:
|
||||
- -s -w
|
||||
- -X main.version={{.Version}}
|
||||
|
||||
targets:
|
||||
- os: linux
|
||||
arch: amd64
|
||||
- os: linux
|
||||
arch: arm64
|
||||
- os: darwin
|
||||
arch: arm64
|
||||
|
||||
sign:
|
||||
enabled: true
|
||||
gpg:
|
||||
key: $GPG_KEY_ID
|
||||
macos:
|
||||
identity: "Developer ID Application: Your Name (TEAM_ID)"
|
||||
notarize: false
|
||||
apple_id: $APPLE_ID
|
||||
team_id: $APPLE_TEAM_ID
|
||||
app_password: $APPLE_APP_PASSWORD
|
||||
```
|
||||
Optional `.core/build.yaml` - see [Configuration](example.md#configuration) for examples.
|
||||
|
||||
## Code Signing
|
||||
|
||||
|
|
@ -169,3 +156,21 @@ core build --notarize
|
|||
| `APPLE_ID` | Apple account email |
|
||||
| `APPLE_TEAM_ID` | Apple Developer Team ID |
|
||||
| `APPLE_APP_PASSWORD` | App-specific password for notarization |
|
||||
|
||||
## Building from PWAs and Static Sites
|
||||
|
||||
### Build from Local Directory
|
||||
|
||||
Build a desktop app from static web application files:
|
||||
|
||||
```bash
|
||||
core build from-path --path ./dist
|
||||
```
|
||||
|
||||
### Build from Live PWA
|
||||
|
||||
Build a desktop app from a live Progressive Web App URL:
|
||||
|
||||
```bash
|
||||
core build pwa --url https://example.com
|
||||
```
|
||||
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
|
||||
|
||||
Portable development environment with 100+ embedded tools.
|
||||
Multi-repo workflow and portable development environment.
|
||||
|
||||
## Overview
|
||||
|
||||
Core DevOps provides a sandboxed, immutable development environment based on LinuxKit. It includes AI tools (Claude, Gemini), runtimes (Go, Node, PHP, Python, Rust), and infrastructure tools (Docker, Kubernetes, Terraform).
|
||||
|
||||
## Commands
|
||||
## Multi-Repo Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `install` | Download the core-devops image for your platform |
|
||||
| `boot` | Start the development environment |
|
||||
| `stop` | Stop the running environment |
|
||||
| `status` | Show environment status |
|
||||
| `shell` | Open a shell in the environment |
|
||||
| `serve` | Mount project and start dev server |
|
||||
| `test` | Run tests inside the environment |
|
||||
| `claude` | Start sandboxed Claude session |
|
||||
| `update` | Update to latest image |
|
||||
| [work](work/) | Full workflow: status + commit + push |
|
||||
| `health` | Quick health check across repos |
|
||||
| `commit` | Claude-assisted commits |
|
||||
| `push` | Push repos with unpushed commits |
|
||||
| `pull` | Pull repos that are behind |
|
||||
| `issues` | List open issues |
|
||||
| `reviews` | List PRs needing review |
|
||||
| `ci` | Check CI status |
|
||||
| `impact` | Show dependency impact |
|
||||
| `api` | Tools for managing service APIs |
|
||||
| `sync` | Synchronize public service APIs |
|
||||
|
||||
## Task Management Commands
|
||||
|
||||
> **Note:** Task management commands have moved to [`core ai`](../ai/).
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| [`ai tasks`](../ai/) | List available tasks from core-agentic |
|
||||
| [`ai task`](../ai/) | Show task details or auto-select a task |
|
||||
| [`ai task:update`](../ai/) | Update task status or progress |
|
||||
| [`ai task:complete`](../ai/) | Mark a task as completed |
|
||||
| [`ai task:commit`](../ai/) | Auto-commit changes with task reference |
|
||||
| [`ai task:pr`](../ai/) | Create a pull request for a task |
|
||||
|
||||
## Dev Environment Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `install` | Download the core-devops image |
|
||||
| `boot` | Start the environment |
|
||||
| `stop` | Stop the environment |
|
||||
| `status` | Show status |
|
||||
| `shell` | Open shell |
|
||||
| `serve` | Start dev server |
|
||||
| `test` | Run tests |
|
||||
| `claude` | Sandboxed Claude |
|
||||
| `update` | Update image |
|
||||
|
||||
---
|
||||
|
||||
## Dev Environment Overview
|
||||
|
||||
Core DevOps provides a sandboxed, immutable development environment based on LinuxKit with 100+ embedded tools.
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
|
@ -39,24 +70,16 @@ core dev serve
|
|||
Download the core-devops image for your platform.
|
||||
|
||||
```bash
|
||||
core dev install [flags]
|
||||
core dev install
|
||||
```
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--source` | Image source: `github`, `registry`, `cdn` (default: auto) |
|
||||
| `--force` | Force re-download even if exists |
|
||||
Downloads the platform-specific dev environment image including Go, PHP, Node.js, Python, Docker, and Claude CLI. Downloads are cached at `~/.core/images/`.
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Download image (auto-detects platform)
|
||||
core dev install
|
||||
|
||||
# Force re-download
|
||||
core dev install --force
|
||||
```
|
||||
|
||||
## dev boot
|
||||
|
|
@ -72,8 +95,8 @@ core dev boot [flags]
|
|||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--memory` | Memory allocation in MB (default: 4096) |
|
||||
| `--cpus` | Number of CPUs (default: 4) |
|
||||
| `--name` | Container name (default: core-dev) |
|
||||
| `--cpus` | Number of CPUs (default: 2) |
|
||||
| `--fresh` | Stop existing and start fresh |
|
||||
|
||||
### Examples
|
||||
|
||||
|
|
@ -82,7 +105,10 @@ core dev boot [flags]
|
|||
core dev boot
|
||||
|
||||
# More resources
|
||||
core dev boot --memory 8192 --cpus 8
|
||||
core dev boot --memory 8192 --cpus 4
|
||||
|
||||
# Fresh start
|
||||
core dev boot --fresh
|
||||
```
|
||||
|
||||
## dev shell
|
||||
|
|
@ -90,9 +116,11 @@ core dev boot --memory 8192 --cpus 8
|
|||
Open a shell in the running environment.
|
||||
|
||||
```bash
|
||||
core dev shell [flags]
|
||||
core dev shell [flags] [-- command]
|
||||
```
|
||||
|
||||
Uses SSH by default, or serial console with `--console`.
|
||||
|
||||
### Flags
|
||||
|
||||
| Flag | Description |
|
||||
|
|
@ -107,6 +135,9 @@ core dev shell
|
|||
|
||||
# Serial console (for debugging)
|
||||
core dev shell --console
|
||||
|
||||
# Run a command
|
||||
core dev shell -- ls -la
|
||||
```
|
||||
|
||||
## dev serve
|
||||
|
|
@ -155,11 +186,11 @@ core dev test [flags] [-- custom command]
|
|||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--unit` | Run only unit tests |
|
||||
| `--name` | Run named test command from `.core/test.yaml` |
|
||||
|
||||
### Test Detection
|
||||
|
||||
Core auto-detects the test framework:
|
||||
Core auto-detects the test framework or uses `.core/test.yaml`:
|
||||
|
||||
1. `.core/test.yaml` - Custom config
|
||||
2. `composer.json` → `composer test`
|
||||
|
|
@ -174,29 +205,16 @@ Core auto-detects the test framework:
|
|||
# Auto-detect and run tests
|
||||
core dev test
|
||||
|
||||
# Run named test from config
|
||||
core dev test --name integration
|
||||
|
||||
# Custom command
|
||||
core dev test -- go test -v ./pkg/...
|
||||
```
|
||||
|
||||
### Test Configuration
|
||||
|
||||
Create `.core/test.yaml` for custom test setup:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
|
||||
commands:
|
||||
- name: unit
|
||||
run: vendor/bin/pest --parallel
|
||||
- name: types
|
||||
run: vendor/bin/phpstan analyse
|
||||
- name: lint
|
||||
run: vendor/bin/pint --test
|
||||
|
||||
env:
|
||||
APP_ENV: testing
|
||||
DB_CONNECTION: sqlite
|
||||
```
|
||||
Create `.core/test.yaml` for custom test setup - see [Configuration](example.md#configuration) for examples.
|
||||
|
||||
## dev claude
|
||||
|
||||
|
|
@ -210,8 +228,9 @@ core dev claude [flags]
|
|||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--no-auth` | Clean session without host credentials |
|
||||
| `--auth` | Selective auth forwarding (e.g., `gh,anthropic`) |
|
||||
| `--model` | Model to use (`opus`, `sonnet`) |
|
||||
| `--no-auth` | Don't forward any auth credentials |
|
||||
| `--auth` | Selective auth forwarding (`gh`, `anthropic`, `ssh`, `git`) |
|
||||
|
||||
### What Gets Forwarded
|
||||
|
||||
|
|
@ -227,11 +246,14 @@ By default, these are forwarded to the sandbox:
|
|||
# Full auth forwarding (default)
|
||||
core dev claude
|
||||
|
||||
# Use Opus model
|
||||
core dev claude --model opus
|
||||
|
||||
# Clean sandbox
|
||||
core dev claude --no-auth
|
||||
|
||||
# Only GitHub auth
|
||||
core dev claude --auth=gh
|
||||
# Only GitHub and Anthropic auth
|
||||
core dev claude --auth gh,anthropic
|
||||
```
|
||||
|
||||
### Why Use This?
|
||||
|
|
@ -258,7 +280,7 @@ Output includes:
|
|||
|
||||
## dev update
|
||||
|
||||
Check for and download newer images.
|
||||
Check for and apply updates.
|
||||
|
||||
```bash
|
||||
core dev update [flags]
|
||||
|
|
@ -268,7 +290,17 @@ core dev update [flags]
|
|||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--force` | Force download even if up to date |
|
||||
| `--apply` | Download and apply the update |
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Check for updates
|
||||
core dev update
|
||||
|
||||
# Apply available update
|
||||
core dev update --apply
|
||||
```
|
||||
|
||||
## Embedded Tools
|
||||
|
||||
|
|
@ -293,23 +325,7 @@ The core-devops image includes 100+ tools:
|
|||
|
||||
## Configuration
|
||||
|
||||
Global config in `~/.core/config.yaml`:
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
|
||||
images:
|
||||
source: auto # auto | github | registry | cdn
|
||||
|
||||
cdn:
|
||||
url: https://images.example.com/core-devops
|
||||
|
||||
github:
|
||||
repo: host-uk/core-images
|
||||
|
||||
registry:
|
||||
image: ghcr.io/host-uk/core-devops
|
||||
```
|
||||
Global config in `~/.core/config.yaml` - see [Configuration](example.md#configuration) for examples.
|
||||
|
||||
## Image Storage
|
||||
|
||||
|
|
@ -323,3 +339,50 @@ Images are stored in `~/.core/images/`:
|
|||
├── core-devops-linux-amd64.qcow2
|
||||
└── manifest.json
|
||||
```
|
||||
|
||||
## Multi-Repo Commands
|
||||
|
||||
See the [work](work/) page for detailed documentation on multi-repo commands.
|
||||
|
||||
### dev ci
|
||||
|
||||
Check GitHub Actions workflow status across all repos.
|
||||
|
||||
```bash
|
||||
core dev ci [flags]
|
||||
```
|
||||
|
||||
#### Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--registry` | Path to `repos.yaml` (auto-detected if not specified) |
|
||||
| `--branch` | Filter by branch (default: main) |
|
||||
| `--failed` | Show only failed runs |
|
||||
|
||||
Requires the `gh` CLI to be installed and authenticated.
|
||||
|
||||
### dev api
|
||||
|
||||
Tools for managing service APIs.
|
||||
|
||||
```bash
|
||||
core dev api sync
|
||||
```
|
||||
|
||||
Synchronizes the public service APIs with their internal implementations.
|
||||
|
||||
### dev sync
|
||||
|
||||
Alias for `core dev api sync`. Synchronizes the public service APIs with their internal implementations.
|
||||
|
||||
```bash
|
||||
core dev sync
|
||||
```
|
||||
|
||||
This command scans the `pkg` directory for services and ensures that the top-level public API for each service is in sync with its internal implementation. It automatically generates the necessary Go files with type aliases.
|
||||
|
||||
## See Also
|
||||
|
||||
- [work](work/) - Multi-repo workflow commands (`core dev work`, `core dev health`, etc.)
|
||||
- [ai](../ai/) - Task management commands (`core ai tasks`, `core ai task`, etc.)
|
||||
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
|
||||
|
||||
- [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
|
||||
|
||||
```bash
|
||||
core doctor
|
||||
core doctor [flags]
|
||||
```
|
||||
|
||||
## Flags
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `--verbose` | Show detailed version information |
|
||||
|
||||
## What It Checks
|
||||
|
||||
### Required Tools
|
||||
|
|
@ -71,5 +77,5 @@ All checks passed!
|
|||
|
||||
## See Also
|
||||
|
||||
- [setup command](setup.md) - Clone repos from registry
|
||||
- [dev install](dev.md) - Install development environment
|
||||
- [setup command](../setup/) - Clone repos from registry
|
||||
- [dev](../dev/) - Development environment
|
||||
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.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
core templates [command]
|
||||
core vm templates [command]
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
|
@ -14,13 +14,14 @@ core templates [command]
|
|||
|---------|-------------|
|
||||
| `list` | List available templates |
|
||||
| `show` | Show template details |
|
||||
| `vars` | Show template variables |
|
||||
|
||||
## templates list
|
||||
|
||||
List all available LinuxKit templates.
|
||||
|
||||
```bash
|
||||
core templates list
|
||||
core vm templates list
|
||||
```
|
||||
|
||||
### Output
|
||||
|
|
@ -46,13 +47,13 @@ Available Templates:
|
|||
Show details of a specific template.
|
||||
|
||||
```bash
|
||||
core templates show <name>
|
||||
core vm templates show <name>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
core templates show core-dev
|
||||
core vm templates show core-dev
|
||||
```
|
||||
|
||||
Output:
|
||||
|
|
@ -77,6 +78,28 @@ Services:
|
|||
Size: ~1.8GB
|
||||
```
|
||||
|
||||
## templates vars
|
||||
|
||||
Show variables defined by a template.
|
||||
|
||||
```bash
|
||||
core vm templates vars <name>
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
core vm templates vars core-dev
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
Variables for core-dev:
|
||||
SSH_KEY (required) SSH public key
|
||||
MEMORY (optional) Memory in MB (default: 4096)
|
||||
CPUS (optional) CPU count (default: 4)
|
||||
```
|
||||
|
||||
## Template Locations
|
||||
|
||||
Templates are searched in order:
|
||||
|
|
@ -87,31 +110,15 @@ Templates are searched in order:
|
|||
|
||||
## Creating Templates
|
||||
|
||||
Create a LinuxKit YAML in `.core/linuxkit/`:
|
||||
|
||||
```yaml
|
||||
# .core/linuxkit/myserver.yml
|
||||
kernel:
|
||||
image: linuxkit/kernel:5.15
|
||||
cmdline: "console=tty0"
|
||||
|
||||
init:
|
||||
- linuxkit/init:v1.0.0
|
||||
|
||||
services:
|
||||
- name: sshd
|
||||
image: linuxkit/sshd:v1.0.0
|
||||
- name: myapp
|
||||
image: ghcr.io/myorg/myapp:latest
|
||||
```
|
||||
Create a LinuxKit YAML in `.core/linuxkit/`. See [Template Format](example.md#template-format) for examples.
|
||||
|
||||
Run with:
|
||||
|
||||
```bash
|
||||
core run --template myserver
|
||||
core vm run --template myserver
|
||||
```
|
||||
|
||||
## See Also
|
||||
|
||||
- [run command](run.md) - Run LinuxKit images
|
||||
- [build command](build.md) - Build LinuxKit images
|
||||
- [vm command](../) - Run LinuxKit images
|
||||
- [build command](../../build/) - Build LinuxKit images
|
||||
|
|
@ -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
|
||||
```
|
||||
|
||||
## repos.yaml
|
||||
|
||||
Package registry for multi-repo workspaces:
|
||||
|
||||
```yaml
|
||||
# Organisation name (used for GitHub URLs)
|
||||
org: host-uk
|
||||
|
||||
# Base path for cloning (default: current directory)
|
||||
base_path: .
|
||||
|
||||
# Default settings for all repos
|
||||
defaults:
|
||||
ci: github
|
||||
license: EUPL-1.2
|
||||
branch: main
|
||||
|
||||
# Repository definitions
|
||||
repos:
|
||||
# Foundation packages (no dependencies)
|
||||
core-php:
|
||||
type: foundation
|
||||
description: Foundation framework
|
||||
|
||||
core-devops:
|
||||
type: foundation
|
||||
description: Development environment
|
||||
clone: false # Skip during setup (already exists)
|
||||
|
||||
# Module packages (depend on foundation)
|
||||
core-tenant:
|
||||
type: module
|
||||
depends_on: [core-php]
|
||||
description: Multi-tenancy module
|
||||
|
||||
core-admin:
|
||||
type: module
|
||||
depends_on: [core-php, core-tenant]
|
||||
description: Admin panel
|
||||
|
||||
core-api:
|
||||
type: module
|
||||
depends_on: [core-php]
|
||||
description: REST API framework
|
||||
|
||||
# Product packages (user-facing applications)
|
||||
core-bio:
|
||||
type: product
|
||||
depends_on: [core-php, core-tenant]
|
||||
description: Link-in-bio product
|
||||
domain: bio.host.uk.com
|
||||
|
||||
core-social:
|
||||
type: product
|
||||
depends_on: [core-php, core-tenant]
|
||||
description: Social scheduling
|
||||
domain: social.host.uk.com
|
||||
|
||||
# Templates
|
||||
core-template:
|
||||
type: template
|
||||
description: Starter template for new projects
|
||||
```
|
||||
|
||||
### repos.yaml Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `org` | Yes | GitHub organisation name |
|
||||
| `base_path` | No | Directory for cloning (default: `.`) |
|
||||
| `defaults` | No | Default settings applied to all repos |
|
||||
| `repos` | Yes | Map of repository definitions |
|
||||
|
||||
### Repository Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `type` | Yes | `foundation`, `module`, `product`, or `template` |
|
||||
| `description` | No | Human-readable description |
|
||||
| `depends_on` | No | List of package dependencies |
|
||||
| `clone` | No | Set `false` to skip during setup |
|
||||
| `domain` | No | Production domain (for products) |
|
||||
| `branch` | No | Override default branch |
|
||||
|
||||
### Package Types
|
||||
|
||||
| Type | Description | Dependencies |
|
||||
|------|-------------|--------------|
|
||||
| `foundation` | Core framework packages | None |
|
||||
| `module` | Reusable modules | Foundation packages |
|
||||
| `product` | User-facing applications | Foundation + modules |
|
||||
| `template` | Starter templates | Any |
|
||||
|
||||
---
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Complete reference of environment variables used by Core CLI.
|
||||
|
||||
### Authentication
|
||||
|
||||
| Variable | Used By | Description |
|
||||
|----------|---------|-------------|
|
||||
| `GITHUB_TOKEN` | `core ci`, `core dev` | GitHub API authentication |
|
||||
| `ANTHROPIC_API_KEY` | `core ai`, `core dev claude` | Claude API key |
|
||||
| `AGENTIC_TOKEN` | `core ai task*` | Agentic API authentication |
|
||||
| `AGENTIC_BASE_URL` | `core ai task*` | Agentic API endpoint |
|
||||
|
||||
### Publishing
|
||||
|
||||
| Variable | Used By | Description |
|
||||
|----------|---------|-------------|
|
||||
| `NPM_TOKEN` | `core ci` (npm publisher) | npm registry auth token |
|
||||
| `CHOCOLATEY_API_KEY` | `core ci` (chocolatey publisher) | Chocolatey API key |
|
||||
| `DOCKER_USERNAME` | `core ci` (docker publisher) | Docker registry username |
|
||||
| `DOCKER_PASSWORD` | `core ci` (docker publisher) | Docker registry password |
|
||||
|
||||
### Deployment
|
||||
|
||||
| Variable | Used By | Description |
|
||||
|----------|---------|-------------|
|
||||
| `COOLIFY_URL` | `core php deploy` | Coolify server URL |
|
||||
| `COOLIFY_TOKEN` | `core php deploy` | Coolify API token |
|
||||
| `COOLIFY_APP_ID` | `core php deploy` | Production application ID |
|
||||
| `COOLIFY_STAGING_APP_ID` | `core php deploy --staging` | Staging application ID |
|
||||
|
||||
### Build
|
||||
|
||||
| Variable | Used By | Description |
|
||||
|----------|---------|-------------|
|
||||
| `CGO_ENABLED` | `core build`, `core go *` | Enable/disable CGO (default: 0) |
|
||||
| `GOOS` | `core build` | Target operating system |
|
||||
| `GOARCH` | `core build` | Target architecture |
|
||||
|
||||
### Configuration Paths
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `GITHUB_TOKEN` | GitHub authentication (via gh CLI) |
|
||||
| `NPM_TOKEN` | npm publish token |
|
||||
| `CHOCOLATEY_API_KEY` | Chocolatey publish key |
|
||||
| `COOLIFY_TOKEN` | Coolify deployment token |
|
||||
| `CORE_CONFIG` | Override config directory (default: `~/.core/`) |
|
||||
| `CORE_REGISTRY` | Override repos.yaml path |
|
||||
|
||||
---
|
||||
|
||||
## Defaults
|
||||
|
||||
|
|
|
|||
|
|
@ -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