Skip to content

Version 0

MortelOS App Standards

MortelOS-owned Laravel runtime defaults for host applications.

mortelos/app-standards owns the Laravel runtime defaults every MortelOS host app should start with. It also carries the Spine contract: the governance rules every MortelOS portal inherits. This page describes version 0.1.3.

This package is intentionally a MortelOS-owned hard-fork-style reimplementation, not a runtime dependency on nunomaduro/essentials. Upstream packages and community conventions can inspire defaults, but MortelOS owns the behavior, names, tests and release cadence.

Why It Exists

App-wide Laravel defaults are powerful. They affect Eloquent, validation, URLs, console safety and test behavior. Putting those defaults in a small MortelOS package gives every host app the same baseline without making reusable feature packages carry app-level side effects.

Use this package in host apps such as mortelos/starter and other concrete OS installations. Do not require it from reusable packages such as mortelos/framework, channels, widgets or studio packages.

Defaults

Area Default
Eloquent Strict models are enabled.
Relationships Automatic relationship eager loading is enabled.
Mass assignment Models stay guarded. Unguarding is available but off.
Dates Laravel's date factory returns immutable dates.
URLs HTTPS URL generation is forced in production.
Console safety Destructive migration and database commands are prohibited in production.
Tests Stray HTTP requests are prevented in testing.
Tests Sleep is faked in testing.
Validation Password defaults use a minimum length of 12, max length of 255 and uncompromised checks.

Console safety is production-only on purpose. Test suites and local setup commands still need migrations such as migrate:fresh and RefreshDatabase.

Install In A Host App

composer require mortelos/app-standards

The package resolves from the MortelOS registry. Configure registry access once before installing; see Installation.

The package needs PHP 8.4 and Laravel 13. The service provider is auto-discovered.

To test a local checkout of the package against a host app, symlink it into vendor/ after installing. Do not add a path repository to the committed composer.json; see Packages.

Configuration

Publish the config when a host needs to override a default:

php artisan vendor:publish --tag=mortelos-app-standards-config

The published file is config/app-standards.php. Each switch also has an environment variable:

Key Environment variable Default
strict_models MORTELOS_STANDARDS_STRICT_MODELS true
auto_eager_loading MORTELOS_STANDARDS_AUTO_EAGER_LOADING true
unguard_models MORTELOS_STANDARDS_UNGUARD_MODELS false
immutable_dates MORTELOS_STANDARDS_IMMUTABLE_DATES true
force_https.enabled MORTELOS_STANDARDS_FORCE_HTTPS true, in production
safe_console.enabled MORTELOS_STANDARDS_SAFE_CONSOLE true, in production
prevent_stray_requests.enabled MORTELOS_STANDARDS_PREVENT_STRAY_REQUESTS true, in testing
fake_sleep.enabled MORTELOS_STANDARDS_FAKE_SLEEP true, in testing
passwords.enabled MORTELOS_STANDARDS_PASSWORDS true

The environment-bound defaults have an environments list in the config file. An empty list applies the default in every environment. With fake_sleep.sync_with_carbon (default false), faked sleeps also move Carbon's test clock. The password rule reads passwords.min, passwords.max, passwords.uncompromised and passwords.compromised_threshold.

Prefer environment-specific toggles over removing the package. If a default is wrong for most MortelOS hosts, change it in this package and cover the behavior with a package test.

Spine Contract

The Spine is the governance default every MortelOS portal inherits:

Clause Rule
C1 Reading in-scope data is direct. No proposal, no approval.
C2 Every mutation of governed state goes through a human-approved proposal.
C3 Access is deny-by-default across entities, links, tools and surfaces.
C4 The audit trail is immutable and event-sourced.

Publish the contract and its config with:

php artisan vendor:publish --tag=mortelos-spine-contract

This writes config/spine.php and .mortelos/spine-contract.md. The config holds:

Key What it holds
governed_models Framework models whose rows are governed state: entities, entity links, policies, roles, inbox items, channels, workflows, workflow runs, documents and document versions.
writers fnmatch() patterns of classes that may write governed models directly. The defaults are the framework and App\ aggregates and projectors.
writer_attributes Attributes that mark a sanctioned writer. The default is Mortelos\AppStandards\Spine\GovernedWriter.

Tag a governed action that does not fit the namespace patterns with the attribute. It takes an optional reason and changes no runtime behaviour:

use Mortelos\AppStandards\Spine\GovernedWriter;

#[GovernedWriter(reason: 'Applies an approved proposal')]
final class ApplyApprovedChange
{
    // ...
}

mortelos/dev-tools checks the contract. php artisan mortelos:spine:check proves the rails exist and are connected. Its PHPStan rule flags direct writes to governed models from other classes; @spine-ignore on the line silences a deliberate exception. Include the rule in phpstan.neon:

includes:
    - vendor/mortelos/dev-tools/extension.neon

Neither check proves that a mutation really went through a proposal a human approved. Keep a test in every portal for its proposal path: propose, pending, human approves, state changes, event recorded.

Outlets

An outlet is a place where you extend mortelos/app-standards from your app without changing the package. The table lists the outlets in its resources/mortelos/outlets.json as of version 0.1.3; read Outlets for how each kind works and what to do when none fits.

php artisan mortelos:outlets:list app-standards
Kind Name What it is for
config spine Configure the governed models and permitted writers used by the spine checks. Publish with php artisan vendor:publish --tag=mortelos-spine-contract.
config app-standards Configure the runtime defaults applied by app-standards. Publish with php artisan vendor:publish --tag=mortelos-app-standards-config.

Boundaries

mortelos/app-standards owns app runtime defaults and the Spine contract text and config. It does not own portal features, domain policy, tenant branding, connectors, widgets, dashboards or MCP tools. The checks that enforce the Spine live in mortelos/dev-tools. The package does not depend on mortelos/framework: the Spine config names framework classes as strings.

Reusable packages should remain installable without these defaults. Host apps opt into the standards package directly.