Developer-Dashboard

 view release on metacpan or  search on metacpan

doc/update-and-release.md  view on Meta::CPAN

- V6 Stored Cryptography
- V7 Error Handling and Logging
- V8 Data Protection
- V9 Communication
- V10 Malicious Code
- V11 Business Logic
- V12 Files and Resources
- V13 API and Web Service
- V14 Configuration

Treat ASVS Level 2 rigor as the default floor for this repository, and require
Level 3 review when the change touches higher-trust boundaries such as auth,
sessions, cryptographic handling, release signing, or externally callable API
routes.

Also map the change against the OWASP Top 10 2021 categories, with explicit
attention to:

- `A01` Broken Access Control
- `A02` Cryptographic Failures
- `A03` Injection
- `A04` Insecure Design
- `A05` Security Misconfiguration
- `A06` Vulnerable and Outdated Components
- `A07` Identification and Authentication Failures
- `A08` Software and Data Integrity Failures
- `A09` Security Logging and Monitoring Failures
- `A10` Server-Side Request Forgery

Use the commands in `SECURITY_CHECKS.md` as the local repo-side evidence set.
Do not claim the security review is complete merely because the code “looks
fine”; the grep-based audit, focused tests, and release/integration gates are
part of the proof.

The shipped OWASP compliance SOW is also part of that proof. Keep the
chapter-by-chapter evidence record current and do not upgrade the public
wording from `OWASP-aligned` / `OWASP-gated` to blanket `OWASP compliant`
until the SOW closure criteria and the remaining governance gates are
actually closed.

## Local Update

Run:

```bash
perl -Ilib bin/dashboard version
mkdir -p ~/.developer-dashboard/cli/update.d
printf '#!/usr/bin/env perl\nuse Developer::Dashboard::Runtime::Result;\nprint Developer::Dashboard::Runtime::Result::stdout(q{01-runtime});\nprint $ENV{RESULT} // q{}\n' > ~/.developer-dashboard/cli/update
chmod +x ~/.developer-dashboard/cli/update
printf '#!/bin/sh\necho runtime-update\n' > ~/.developer-dashboard/cli/update.d/01-runtime
chmod +x ~/.developer-dashboard/cli/update.d/01-runtime
perl -Ilib bin/dashboard update
```

This executes ordered scripts from either `~/.developer-dashboard/cli/update`
or `~/.developer-dashboard/cli/update.d`:

1. sorted by filename
2. running any regular executable file
3. skipping non-executable files
4. streaming each hook file's stdout and stderr live while still accumulating `RESULT` JSON
5. rewriting `RESULT` after each hook so later hook files can react to earlier output
6. passing the final `RESULT` JSON to the real command

`dashboard update` has no special built-in path. If you want it, provide it as
a normal user command and let its hook files run through the same top-level
command-hook path as every other dashboard subcommand.

Perl hook scripts can use `Developer::Dashboard::Runtime::Result` to decode `RESULT` and read
structured hook output without hand-parsing the JSON blob. If the final Perl
command wants a compact summary after the hook chain finishes, it can call
`Developer::Dashboard::Runtime::Result->report()`.

Use `dashboard version` to print the installed Developer Dashboard version.

Before a release or push, regenerate the checkout manual with:

```bash
script/sync-readme-from-pod
```

The canonical manual source is the POD inside `lib/Developer/Dashboard.pm`.
`README.md` is a generated checkout artifact and must not be hand-edited as a
second independent manual.

The blank-container integration harness now installs the tarball first and then
builds a fake-project `./.developer-dashboard` tree so the shipped test suite
still starts from a clean runtime before exercising project-local overrides.
When a code change introduces a new non-core runtime Perl module, declare it in
`Makefile.PL`, `cpanfile`, and `dist.ini` in the same change. The release
metadata guardrail now fails if those three files drift apart, so do not rely
on one metadata source to imply the others.
Do not leave source-tree bootstrap in shipped library modules. If a `.pm` file
needs `FindBin` or a checkout-relative `use lib`, it is almost certainly in
the wrong layer. Keep that logic in scripts or tests, then prove the built
distribution from its unpacked tarball before release.
Inline POD changes must also pass `prove -lv t/37-pod-syntax.t`, and release
metadata changes must leave the built tarball carrying shipped security and
contribution guidance rather than relying on checkout-only Markdown files.
The release tarball must also keep `doc/integration-test-plan.md`,
`doc/testing.md`, `doc/windows-testing.md`, and the `integration/` helpers,
because install-time tarball verification reads those shipped files directly
instead of assuming a source checkout is present.
Release artifact cleanup is now a tested invariant: after the documented
`rm -rf Developer-Dashboard-* Developer-Dashboard-*.tar.gz` plus `dzil build`
sequence, the repository root must contain exactly one unpacked
`Developer-Dashboard-X.XX/` build directory and exactly one matching
`Developer-Dashboard-X.XX.tar.gz` tarball. If stale build directories remain,
the tarball kwalitee gate must fail.
After the source-tree `prove -lr t` and explicit `Devel::Cover` gates pass,
verify the built tarball still installs in a blank Perl container with:

```bash
docker run --rm -v "$PWD:/work" -w /work perl:5.38-bookworm \
  sh -lc 'cpanm --notest /work/Developer-Dashboard-X.XX.tar.gz -v'
```

That blank-container step is now an installation-verification gate. It keeps
the packaged dependency-resolution and installed-runtime check, but it does
not rerun the full distribution test suite a second time because the normal
source-tree test and coverage gates already covered that work.

doc/update-and-release.md  view on Meta::CPAN

```

Restart the web service and configured collector loops:

```bash
perl -Ilib bin/dashboard restart
```

Customize runtime locations:

```bash
export DEVELOPER_DASHBOARD_BOOKMARKS="$HOME/my-dd-pages"
export DEVELOPER_DASHBOARD_CONFIGS="$HOME/my-dd-config"
export DEVELOPER_DASHBOARD_CHECKERS="docker.health:repo.status"
```

Access semantics:

- `http://127.0.0.1:7890/`, `http://[::1]:7890/`, and `http://localhost:7890/` are trusted as local admin when the request still arrives from loopback
- a custom alias hostname is trusted as local admin only when it is listed under `web.ssl_subject_alt_names` and the request still arrives from loopback
- outsider access returns `401` with an empty body until at least one helper user exists in the active dashboard runtime
- once a helper user exists, outsider access receives the helper login page

When helper access is redirected to `/login`, the login form must preserve the
original target path and query in a hidden redirect field so a successful
helper login returns the browser to the original route, such as `/app/index`,
instead of always sending it to `/`.

The default bind is `0.0.0.0:7890`, so the service is reachable on local and VPN interfaces unless the host firewall blocks it.
Run `dashboard serve --ssl` to enable HTTPS with the generated self-signed
certificate stored under `~/.developer-dashboard/certs/`, and verify the local
listener at `https://127.0.0.1:7890/`. When SSL is enabled, the public HTTP
socket on that same host and port must return a same-port `307` redirect to
the equivalent `https://...` URL before the dashboard route runs, and a real
browser should then land on the expected self-signed certificate warning page
instead of a connection reset. The generated cert must include SAN coverage for
`localhost`, `127.0.0.1`, and `::1`, plus the concrete non-wildcard bind host
and any configured `web.ssl_subject_alt_names`, and older dashboard certs must
be regenerated automatically when they do not match that browser-safe server
profile.
Shared `nav/*.tt` fragments now wrap horizontally and inherit bookmark theme
colors from CSS variables, so bookmark pages with dark panels do not force a
light nav strip or unreadable nav link text.

Process management does not trust pid files alone. The runtime validates managed web and collector processes by environment marker or process title, and uses a `pkill`-style scan fallback when pid state is stale.

Security baseline:

- helper passwords must be at least 8 characters long
- helper sessions are remote-bound and expire automatically
- the local server adds CSP, frame-deny, nosniff, no-referrer, and no-store headers

The extension layer now includes:

- config-backed provider pages resolved through the page resolver
- action execution through the page action runner
- user CLI hook directories under `~/.developer-dashboard/cli`
- project-aware Docker Compose resolution through `dashboard docker compose`

Compose setup can now stay isolated in service folders under `./.developer-dashboard/config/docker/<service>/compose.yml` for the current project, with `~/.developer-dashboard/config/docker/<service>/compose.yml` as the fallback. The wrapper infers s...
Without `--dry-run`, the wrapper now hands off with `exec`, so terminal users see the normal streaming output from `docker compose` itself instead of a dashboard JSON wrapper.
Path aliases can now be managed from the CLI with `dashboard path add <name> <path>` and `dashboard path del <name>`. These commands persist user-defined aliases in the effective config root, using a project-local `./.developer-dashboard` tree first ...
Use `Developer::Dashboard::Folder` for runtime path helpers. It resolves the
same root-style names exposed by `dashboard paths`, including runtime,
bookmark, config, and configured alias names such as `docker`, without relying
on unscoped CPAN-global module names.
`dashboard init` now seeds the current dashboard-managed starter pages as editable saved bookmarks when those ids are missing. Re-running init keeps existing user config intact, creates `config.json` as `{}` only when it is missing, keeps dashboard-m...
`dashboard cpan <Module...>` now manages optional runtime Perl modules under `./.developer-dashboard/local` and appends matching requirements to `./.developer-dashboard/cpanfile`, while keeping the implementation in `bin/dashboard` and letting saved ...

## Release To PAUSE

The GitHub workflow:

- `.github/workflows/release-cpan.yml`

builds the release using Dist::Zilla:

```bash
rm -rf Developer-Dashboard-* Developer-Dashboard-*.tar.gz
dzil build
```

Before publishing to PAUSE, remove older build directories and tarballs first so only the current release artifact remains, then validate the exact tarball that will ship:

```bash
rm -rf Developer-Dashboard-* Developer-Dashboard-*.tar.gz
dzil build
prove -lv t/36-release-kwalitee.t
tar -tzf Developer-Dashboard-1.46.tar.gz | grep run-host-integration.sh
cpanm /tmp/Developer-Dashboard-1.46.tar.gz -v
```

The release gather rules must also exclude local coverage output such as
`cover_db`, so a covered test run before `dzil build` does not leak
Devel::Cover artifacts into the public tarball.
Treat `t/36-release-kwalitee.t` as the explicit 100 percent kwalitee gate for
the tarball that will ship. It analyzes the built release archive through
`Module::CPANTS::Analyse`, and it is the correct local check when a CPANTS
page claims something lower than full marks. The CPANTS modules used by this
gate are release-only tooling and must not appear in the generated install-time
test prerequisites for blank-environment `cpanm` verification.

Scorecard now also expects a real GitHub release asset set, not just a local
tag. After the release tarball is built and verified, publish a GitHub release
for the matching `vX.XX` tag and attach:

- `Developer-Dashboard-X.XX.tar.gz`
- `Developer-Dashboard-X.XX.tar.gz.sha256`
- `Developer-Dashboard-X.XX.tar.gz.asc`

The release asset names matter because Scorecard only evaluates what exists on
the GitHub release page. A local tag or PAUSE upload alone is not enough for
the `Signed-Releases` check to observe anything.

The GitHub release automation now lives in:

- `.github/workflows/release-github.yml`

That workflow rebuilds and retests before publishing the release asset set,
adds explicit `concurrency` and `timeout-minutes` guards so a hung job cannot
sit forever, then creates or updates the GitHub release and uploads the



( run in 0.536 second using v1.01-cache-2.11-cpan-6aa56a78535 )