Add Laravel Truss for live schema diagrams.
Install albertoarena/laravel-truss as a local-only tool so /truss and the optional Truss MCP server can inspect structure without exposing row data.
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
/storage/*.key
|
/storage/*.key
|
||||||
/storage/pail
|
/storage/pail
|
||||||
/vendor
|
/vendor
|
||||||
|
/storage/app/private/truss
|
||||||
_ide_helper.php
|
_ide_helper.php
|
||||||
Homestead.json
|
Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
|
|||||||
@@ -6,6 +6,14 @@
|
|||||||
"artisan",
|
"artisan",
|
||||||
"boost:mcp"
|
"boost:mcp"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"truss": {
|
||||||
|
"command": "php",
|
||||||
|
"args": [
|
||||||
|
"artisan",
|
||||||
|
"mcp:start",
|
||||||
|
"truss"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,6 +280,20 @@ composer test
|
|||||||
php artisan test
|
php artisan test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Schema viewer (Laravel Truss)
|
||||||
|
|
||||||
|
[Laravel Truss](https://github.com/albertoarena/laravel-truss) is installed as a **dev** dependency. In `local`, open:
|
||||||
|
|
||||||
|
```
|
||||||
|
/truss
|
||||||
|
```
|
||||||
|
|
||||||
|
It shows a live ER diagram of your schema (structure only, never row data). Optional agent MCP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php artisan mcp:start truss
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"symfony/polyfill-iconv": "^1.37"
|
"symfony/polyfill-iconv": "^1.37"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"albertoarena/laravel-truss": "^1.8",
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
"laravel/boost": "^2.5",
|
"laravel/boost": "^2.5",
|
||||||
"laravel/pail": "^1.2.5",
|
"laravel/pail": "^1.2.5",
|
||||||
|
|||||||
Generated
+143
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "d2a98af0564164e3228a1b7712e36e87",
|
"content-hash": "eb8ccdae5381401eaa99d07ff82ce500",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-crt-php",
|
"name": "aws/aws-crt-php",
|
||||||
@@ -8941,6 +8941,87 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
|
{
|
||||||
|
"name": "albertoarena/laravel-truss",
|
||||||
|
"version": "v1.8.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/albertoarena/laravel-truss.git",
|
||||||
|
"reference": "d8750756f5f239066c7f0d6e40b0eeb7e7e435bf"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/albertoarena/laravel-truss/zipball/d8750756f5f239066c7f0d6e40b0eeb7e7e435bf",
|
||||||
|
"reference": "d8750756f5f239066c7f0d6e40b0eeb7e7e435bf",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^12.0 || ^13.0",
|
||||||
|
"illuminate/support": "^12.0 || ^13.0",
|
||||||
|
"php": "^8.3",
|
||||||
|
"spatie/laravel-package-tools": "^1.16"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/mcp": "^0.9",
|
||||||
|
"laravel/pint": "^1.18",
|
||||||
|
"orchestra/testbench": "^10.0 || ^11.0",
|
||||||
|
"pestphp/pest": "^3.5"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"laravel/mcp": "Enables the optional read-only, structure-only Truss MCP server (Truss as AI context). Opt in with `composer require laravel/mcp`. Needs Laravel >= 12.41.1 or 13."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"AlbertoArena\\Truss\\TrussServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"AlbertoArena\\Truss\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Alberto Arena",
|
||||||
|
"email": "arena.alberto@gmail.com",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A live database structure viewer for Laravel. Renders your schema (never data) as a scrollable, zoomable ER diagram.",
|
||||||
|
"homepage": "https://trussphp.com",
|
||||||
|
"keywords": [
|
||||||
|
"DBML",
|
||||||
|
"data-dictionary",
|
||||||
|
"database",
|
||||||
|
"database-diagram",
|
||||||
|
"er-diagram",
|
||||||
|
"erd",
|
||||||
|
"introspection",
|
||||||
|
"laravel",
|
||||||
|
"mermaid",
|
||||||
|
"migrations",
|
||||||
|
"schema"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"docs": "https://trussphp.com",
|
||||||
|
"issues": "https://github.com/albertoarena/laravel-truss/issues",
|
||||||
|
"source": "https://github.com/albertoarena/laravel-truss"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://ko-fi.com/albertoarena",
|
||||||
|
"type": "ko-fi"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-08-12T14:11:27+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
"version": "3.4.4",
|
"version": "3.4.4",
|
||||||
@@ -11403,6 +11484,67 @@
|
|||||||
],
|
],
|
||||||
"time": "2025-02-07T05:00:38+00:00"
|
"time": "2025-02-07T05:00:38+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-package-tools",
|
||||||
|
"version": "1.93.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-package-tools.git",
|
||||||
|
"reference": "d5552849801f2642aea710557463234b59ef65eb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-package-tools/zipball/d5552849801f2642aea710557463234b59ef65eb",
|
||||||
|
"reference": "d5552849801f2642aea710557463234b59ef65eb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/contracts": "^10.0|^11.0|^12.0|^13.0",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.5",
|
||||||
|
"orchestra/testbench": "^8.0|^9.2|^10.0|^11.0",
|
||||||
|
"pestphp/pest": "^2.1|^3.1|^4.0",
|
||||||
|
"phpunit/php-code-coverage": "^10.0|^11.0|^12.0",
|
||||||
|
"phpunit/phpunit": "^10.5|^11.5|^12.5",
|
||||||
|
"spatie/pest-plugin-test-time": "^2.2|^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\LaravelPackageTools\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Tools for creating Laravel packages",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-package-tools",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-package-tools",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/laravel-package-tools/issues",
|
||||||
|
"source": "https://github.com/spatie/laravel-package-tools/tree/1.93.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2026-05-19T14:06:37+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "staabm/side-effects-detector",
|
"name": "staabm/side-effects-detector",
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
|
|||||||
@@ -0,0 +1,396 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
// Configuration for albertoarena/laravel-truss.
|
||||||
|
// This is the single source of truth for Truss's behaviour. Authorization is a
|
||||||
|
// fixed `viewTruss` gate the host app defines — the ability name is not set here.
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Route prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| URL prefix under which the index page and the JSON schema endpoint are
|
||||||
|
| registered, e.g. "truss" → GET /truss and GET /truss/api/schema.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'route_prefix' => env('TRUSS_ROUTE_PREFIX', 'truss'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Enabled
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Global on/off switch. Defaults to enabled only in the local environment.
|
||||||
|
| Authorization is enforced separately by the fixed `viewTruss` gate.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'enabled' => env('TRUSS_ENABLED', env('APP_ENV', 'production') === 'local'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The middleware stack applied to both Truss routes. Its job is to establish
|
||||||
|
| the auth context (session, cookies, the authenticated user) so the
|
||||||
|
| `viewTruss` gate can identify who is viewing — without it, the gate sees no
|
||||||
|
| user and denies everyone in non-local environments. The default `web` group
|
||||||
|
| covers session-based auth; swap it for a custom guard/Sanctum stack if your
|
||||||
|
| app authenticates differently.
|
||||||
|
|
|
||||||
|
| The fixed `viewTruss` authorization check is always appended after this and
|
||||||
|
| cannot be configured away — this list controls the auth *context*, not
|
||||||
|
| whether authorization runs.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => ['web'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Authorization
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Truss is gated by the fixed `viewTruss` gate (the ability name is not
|
||||||
|
| configurable). In non-local environments the shipped default gate admits
|
||||||
|
| only the emails listed here — the zero-code path for "let these admins in".
|
||||||
|
| Set them via TRUSS_ALLOWED_EMAILS as a comma-separated list, e.g.
|
||||||
|
| TRUSS_ALLOWED_EMAILS="ada@example.com,grace@example.com".
|
||||||
|
|
|
||||||
|
| The list is ignored in local (the gate is not consulted there) and ignored
|
||||||
|
| entirely if the host app defines its own `viewTruss` gate (e.g. a role
|
||||||
|
| check). An empty list fails closed: no one may view in non-local until you
|
||||||
|
| either add emails here or override the gate.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'authorization' => [
|
||||||
|
'allowed_emails' => array_values(array_filter(array_map(
|
||||||
|
'trim',
|
||||||
|
explode(',', (string) env('TRUSS_ALLOWED_EMAILS', '')),
|
||||||
|
))),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Cache
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The schema snapshot is derived, disposable data cached via Laravel's Cache
|
||||||
|
| facade, keyed per connection. `ttl` is in seconds.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'cache' => [
|
||||||
|
'ttl' => (int) env('TRUSS_CACHE_TTL', 3600),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Connections
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Which database connections are visualizable, and any per-connection
|
||||||
|
| overrides. When left empty, Truss uses the application's default
|
||||||
|
| connection (config('database.default')).
|
||||||
|
|
|
||||||
|
| Example:
|
||||||
|
| 'mysql' => ['excluded_tables' => ['legacy_import']],
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'connections' => [
|
||||||
|
//
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Excluded tables
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Tables hidden from the diagram by default (framework/infrastructure noise).
|
||||||
|
| Applied server-side: excluded tables never appear in the API response.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'excluded_tables' => [
|
||||||
|
'migrations',
|
||||||
|
'password_reset_tokens',
|
||||||
|
'sessions',
|
||||||
|
'cache',
|
||||||
|
'cache_locks',
|
||||||
|
'jobs',
|
||||||
|
'job_batches',
|
||||||
|
'failed_jobs',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Diagram
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Styling options passed through to the Mermaid theme, plus the default
|
||||||
|
| column-type label mode:
|
||||||
|
| 'native' → the full DB type (varchar(255), bigint unsigned) [default]
|
||||||
|
| 'laravel' → a best-effort Laravel-style short label (string, integer)
|
||||||
|
| The mode is user-toggleable in the UI; this is only the default.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'diagram' => [
|
||||||
|
'type_labels' => env('TRUSS_TYPE_LABELS', 'native'),
|
||||||
|
|
||||||
|
// Where the browser loads Mermaid from. Null (the default) self-hosts it
|
||||||
|
// from the package's own asset route — no CDN, so a strict CSP needs only
|
||||||
|
// `script-src 'self'`. Set a URL (e.g. a CDN or your own copy) to opt out
|
||||||
|
// of self-hosting: TRUSS_MERMAID_URL=https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js
|
||||||
|
'mermaid_url' => env('TRUSS_MERMAID_URL'),
|
||||||
|
|
||||||
|
// Lower bound for the automatic fit-to-screen: a large schema is never
|
||||||
|
// auto-zoomed below this (it stays legible and you pan). The "Fit" button
|
||||||
|
// ignores this and frames the whole diagram. 1.0 = 100%.
|
||||||
|
'min_zoom' => (float) env('TRUSS_MIN_ZOOM', 0.7),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Theme
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Truss ships a light and dark "blueprint" theme. To match the app Truss is
|
||||||
|
| embedded in, redefine its colours and fonts here. Everything is optional:
|
||||||
|
| only the knobs you set are overridden, the rest stay on the default, so a
|
||||||
|
| handful of values re-skins the whole dashboard (chrome and diagram) in both
|
||||||
|
| light and dark. Config driven, no build step.
|
||||||
|
|
|
||||||
|
| It is delivered as a same-origin stylesheet, so a strict CSP still needs
|
||||||
|
| only style-src 'self' (no inline styles). Each value is validated before it
|
||||||
|
| is emitted; an invalid value is ignored and falls back to the default.
|
||||||
|
|
|
||||||
|
| Colours accept hex, rgb()/rgba()/hsl()/hsla(), or a CSS colour keyword.
|
||||||
|
| Fonts are family names only: name a font your app already loads or a system
|
||||||
|
| font (Truss serves no font files here). Set a knob under both 'light' and
|
||||||
|
| 'dark' to theme both modes; omit 'dark' to theme light only.
|
||||||
|
|
|
||||||
|
| Colour knobs and what each paints:
|
||||||
|
| accent primary accent: headings, PK badges, entity borders, focus ring
|
||||||
|
| accent-secondary secondary accent
|
||||||
|
| background the canvas / page background (and relationship-label backdrop)
|
||||||
|
| surface panels, table bodies, rows, and inputs
|
||||||
|
| surface-alt row striping
|
||||||
|
| text body and diagram text
|
||||||
|
| muted secondary text and the relationship lines / labels
|
||||||
|
| border table, panel, and field lines
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'theme' => [
|
||||||
|
'fonts' => [
|
||||||
|
'mono' => env('TRUSS_THEME_FONT_MONO'),
|
||||||
|
'sans' => env('TRUSS_THEME_FONT_SANS'),
|
||||||
|
],
|
||||||
|
|
||||||
|
'colors' => [
|
||||||
|
'light' => [
|
||||||
|
// 'accent' => '#3730a3',
|
||||||
|
// 'background' => '#ffffff',
|
||||||
|
],
|
||||||
|
'dark' => [
|
||||||
|
// 'accent' => '#a5b4fc',
|
||||||
|
// 'background' => '#0b1020',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Focus
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Focus mode reduces the diagram to a table and its foreign-key neighbours.
|
||||||
|
| `default_depth` is how many hops of neighbours are shown by default.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'focus' => [
|
||||||
|
'default_depth' => (int) env('TRUSS_FOCUS_DEPTH', 1),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Large schema
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Table count above which the UI shows a "large schema — use focus/filter"
|
||||||
|
| warning before rendering everything at once.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'large_schema' => [
|
||||||
|
'warn_above' => (int) env('TRUSS_LARGE_SCHEMA_WARN_ABOVE', 60),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Schema diff
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| "What changed since the last migration". After each migration Truss keeps
|
||||||
|
| the previous schema snapshot as a baseline and compares it against the
|
||||||
|
| current one, surfacing added, removed, and changed tables, columns, indexes,
|
||||||
|
| and foreign keys in the dashboard "Changes" panel and via `truss:diff`.
|
||||||
|
|
|
||||||
|
| This is the only feature that writes to the filesystem: the baseline is a
|
||||||
|
| structure-only JSON file (never row data), stored on disk rather than in the
|
||||||
|
| cache because it cannot be rebuilt from the live database once a migration
|
||||||
|
| has run.
|
||||||
|
|
|
||||||
|
| `enabled`: master switch. When false, no baseline is captured, nothing is
|
||||||
|
| written to disk, the "Changes" toggle is hidden, and `truss:diff` reports the
|
||||||
|
| feature is off. Set it false if you do not want Truss touching your disk.
|
||||||
|
|
|
||||||
|
| `disk`: the filesystem disk the baseline is written to, `local` by default.
|
||||||
|
| The path is always `truss/baselines/{connection}`. This deliberately does not
|
||||||
|
| follow the application's default disk: the baseline is derived tooling state,
|
||||||
|
| not application data, so it should not land in a production bucket, cost
|
||||||
|
| money, or have several instances racing on one object. A failure to read or
|
||||||
|
| write it is never fatal; the diff is simply unavailable until it recovers.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'diff' => [
|
||||||
|
'enabled' => (bool) env('TRUSS_DIFF_ENABLED', true),
|
||||||
|
'disk' => env('TRUSS_DIFF_DISK', 'local'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Doctor
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| `truss:doctor` reviews the schema for problems visible from structure
|
||||||
|
| alone (a table with no primary key, an unindexed foreign key, and so on)
|
||||||
|
| and can fail CI. Structure only: it never reads row data and makes no
|
||||||
|
| network call.
|
||||||
|
|
|
||||||
|
| preset: recommended (high-confidence rules), strict (every rule), none.
|
||||||
|
| rules: per-rule overrides keyed by code: false disables, true enables
|
||||||
|
| (even a heuristic one), ['severity' => 'error'] changes severity.
|
||||||
|
| ignore: per-rule fnmatch patterns (table or table.column) to silence.
|
||||||
|
| fail_on: the severity at or above which the command exits non-zero.
|
||||||
|
| exclude: extra tables to skip, on top of truss.excluded_tables.
|
||||||
|
| dashboard: show the findings in the dashboard "Health" panel. When false,
|
||||||
|
| the schema endpoint sends no doctor payload and the panel and
|
||||||
|
| node badges never appear, leaving the CLI/CI doctor untouched.
|
||||||
|
| flag_tables: always mark tables that have findings on the diagram with a
|
||||||
|
| small severity count, even when the Health panel is closed. Set
|
||||||
|
| false to keep the diagram clean and surface findings only when
|
||||||
|
| the panel is open.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'doctor' => [
|
||||||
|
'preset' => env('TRUSS_DOCTOR_PRESET', 'recommended'),
|
||||||
|
|
||||||
|
'rules' => [
|
||||||
|
// 'TRUSS-INT-002' => true,
|
||||||
|
// 'TRUSS-IDX-001' => ['severity' => 'error'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'ignore' => [
|
||||||
|
// 'TRUSS-IDX-001' => ['audit_log.actor_id'],
|
||||||
|
],
|
||||||
|
|
||||||
|
'fail_on' => env('TRUSS_DOCTOR_FAIL_ON', 'error'),
|
||||||
|
|
||||||
|
'exclude' => [],
|
||||||
|
|
||||||
|
'dashboard' => (bool) env('TRUSS_DOCTOR_DASHBOARD', true),
|
||||||
|
|
||||||
|
'flag_tables' => (bool) env('TRUSS_DOCTOR_FLAG_TABLES', true),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Annotations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Business meaning that cannot be introspected: that status = 1 means paid,
|
||||||
|
| that total_amount is integer cents, that legacy_orders is deprecated. It is
|
||||||
|
| declared here (and/or read from native schema comments) and rendered into
|
||||||
|
| the exports so a coding agent has grounding a type alone cannot give.
|
||||||
|
|
|
||||||
|
| This is still structure only: native comments are part of the CREATE TABLE
|
||||||
|
| definition, not row content, the same boundary as column defaults.
|
||||||
|
|
|
||||||
|
| source: ordered precedence for resolving an annotation; first match
|
||||||
|
| wins. 'config' reads the maps below; 'database' reads native
|
||||||
|
| table/column comments (MySQL and Postgres; SQLite and SQL Server
|
||||||
|
| have none and are skipped). Drop 'database' to ignore DB comments.
|
||||||
|
| notes: global notes rendered in a header block where the format has one.
|
||||||
|
| tables: per-table annotations, keyed by table name.
|
||||||
|
| columns: per-column annotations, keyed by "table.column".
|
||||||
|
|
|
||||||
|
| --no-annotations (and the facade withoutAnnotations()) strip them all.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'annotations' => [
|
||||||
|
'source' => ['config', 'database'],
|
||||||
|
|
||||||
|
'notes' => [
|
||||||
|
// 'All timestamps are UTC.',
|
||||||
|
// 'Monetary columns are integer cents unless stated.',
|
||||||
|
],
|
||||||
|
|
||||||
|
'tables' => [
|
||||||
|
// 'orders' => 'One row per order, not per line item.',
|
||||||
|
],
|
||||||
|
|
||||||
|
'columns' => [
|
||||||
|
// 'orders.status' => '0 draft, 1 paid, 2 refunded',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Export
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| `default_format`: the format truss:export and the facade use when none is
|
||||||
|
| given. One of dbml, json, csv, markdown, mermaid, or llm.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'export' => [
|
||||||
|
'default_format' => env('TRUSS_EXPORT_FORMAT', 'dbml'),
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| MCP server
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The optional read-only, structure-only MCP server exposes the live schema
|
||||||
|
| to a coding agent (structure only, never row data). It requires the
|
||||||
|
| optional first-party `laravel/mcp` package: install it with
|
||||||
|
| `composer require laravel/mcp`. When that package is absent this switch has
|
||||||
|
| no effect (the server is only registered when the package is present), so a
|
||||||
|
| host that does not opt in is unaffected.
|
||||||
|
|
|
||||||
|
| `enabled`: master switch for registering the server once laravel/mcp is
|
||||||
|
| installed. Defaults on, so installing the package is the only opt-in step.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'mcp' => [
|
||||||
|
'enabled' => (bool) env('TRUSS_MCP_ENABLED', true),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user