Add PHP Analyzer Plugin and Composer Lock Data Handling
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Implemented the PhpAnalyzerPlugin to analyze PHP projects. - Created ComposerLockData class to represent data from composer.lock files. - Developed ComposerLockReader to load and parse composer.lock files asynchronously. - Introduced ComposerPackage class to encapsulate package details. - Added PhpPackage class to represent PHP packages with metadata and evidence. - Implemented PhpPackageCollector to gather packages from ComposerLockData. - Created PhpLanguageAnalyzer to perform analysis and emit results. - Added capability signals for known PHP frameworks and CMS. - Developed unit tests for the PHP language analyzer and its components. - Included sample composer.lock and expected output for testing. - Updated project files for the new PHP analyzer library and tests.
This commit is contained in:
5
src/DevPortal/StellaOps.DevPortal.Site/.gitignore
vendored
Normal file
5
src/DevPortal/StellaOps.DevPortal.Site/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
.dist
|
||||
output
|
||||
.cache
|
||||
.DS_Store
|
||||
12
src/DevPortal/StellaOps.DevPortal.Site/TASKS.md
Normal file
12
src/DevPortal/StellaOps.DevPortal.Site/TASKS.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# DevPortal Tasks · Sprint 0206.0001.0001
|
||||
|
||||
Keep this file in sync with `docs/implplan/SPRINT_0206_0001_0001_devportal.md`.
|
||||
|
||||
| Task ID | Status | Notes | Last Updated (UTC) |
|
||||
| --- | --- | --- | --- |
|
||||
| DEVPORT-62-001 | DOING | Select SSG, wire aggregate spec, nav/search scaffold. | 2025-11-22 |
|
||||
| DEVPORT-62-002 | TODO | Schema viewer, examples, copy-curl, version selector. | 2025-11-22 |
|
||||
| DEVPORT-63-001 | TODO | Try-It console against sandbox; token onboarding UX. | 2025-11-22 |
|
||||
| DEVPORT-63-002 | TODO | Embed SDK snippets/quick starts from tested examples. | 2025-11-22 |
|
||||
| DEVPORT-64-001 | TODO | Offline bundle target with specs + SDK archives; zero external assets. | 2025-11-22 |
|
||||
| DEVPORT-64-002 | TODO | Accessibility tests, link checker, performance budgets. | 2025-11-22 |
|
||||
69
src/DevPortal/StellaOps.DevPortal.Site/astro.config.mjs
Normal file
69
src/DevPortal/StellaOps.DevPortal.Site/astro.config.mjs
Normal file
@@ -0,0 +1,69 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import mdx from '@astrojs/mdx';
|
||||
import starlight from '@astrojs/starlight';
|
||||
|
||||
export default defineConfig({
|
||||
site: 'https://devportal.stellaops.local',
|
||||
srcDir: 'src',
|
||||
outDir: 'dist',
|
||||
trailingSlash: 'never',
|
||||
integrations: [
|
||||
mdx(),
|
||||
starlight({
|
||||
title: 'StellaOps DevPortal',
|
||||
description: 'Deterministic, offline-first developer portal for the StellaOps platform.',
|
||||
favicon: {
|
||||
src: '/logo.svg',
|
||||
sizes: 'any',
|
||||
type: 'image/svg+xml',
|
||||
},
|
||||
logo: {
|
||||
src: '/logo.svg',
|
||||
alt: 'StellaOps DevPortal',
|
||||
},
|
||||
customCss: ['./src/styles/custom.css'],
|
||||
social: {
|
||||
github: 'https://git.stella-ops.org',
|
||||
},
|
||||
search: {
|
||||
provider: 'local',
|
||||
algolia: undefined,
|
||||
},
|
||||
sidebar: [
|
||||
{
|
||||
label: 'Overview',
|
||||
items: [
|
||||
{ slug: 'index' },
|
||||
{ slug: 'guides/getting-started' },
|
||||
{ slug: 'guides/navigation-search' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'API',
|
||||
items: [{ slug: 'api-reference' }],
|
||||
},
|
||||
{
|
||||
label: 'Roadmap',
|
||||
items: [{ slug: 'release-notes' }],
|
||||
},
|
||||
],
|
||||
tableOfContents: {
|
||||
minHeadingLevel: 2,
|
||||
maxHeadingLevel: 4,
|
||||
},
|
||||
pagination: true,
|
||||
editLink: {
|
||||
baseUrl: 'https://git.stella-ops.org/devportal',
|
||||
},
|
||||
head: [
|
||||
{
|
||||
tag: 'meta',
|
||||
attrs: {
|
||||
name: 'theme-color',
|
||||
content: '#0f172a',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
8298
src/DevPortal/StellaOps.DevPortal.Site/package-lock.json
generated
Normal file
8298
src/DevPortal/StellaOps.DevPortal.Site/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
src/DevPortal/StellaOps.DevPortal.Site/package.json
Normal file
29
src/DevPortal/StellaOps.DevPortal.Site/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@stellaops/devportal-site",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"engines": {
|
||||
"node": ">=18.18.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev --host",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview",
|
||||
"check": "astro check",
|
||||
"sync:spec": "node scripts/sync-spec.mjs",
|
||||
"prepare:static": "npm run sync:spec && astro check"
|
||||
},
|
||||
"dependencies": {
|
||||
"rapidoc": "9.3.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/mdx": "4.3.12",
|
||||
"@astrojs/starlight": "0.36.2",
|
||||
"@types/node": "24.10.1",
|
||||
"astro": "5.16.0",
|
||||
"typescript": "5.9.3"
|
||||
}
|
||||
}
|
||||
1542
src/DevPortal/StellaOps.DevPortal.Site/public/api/stella.yaml
Normal file
1542
src/DevPortal/StellaOps.DevPortal.Site/public/api/stella.yaml
Normal file
File diff suppressed because it is too large
Load Diff
13
src/DevPortal/StellaOps.DevPortal.Site/public/logo.svg
Normal file
13
src/DevPortal/StellaOps.DevPortal.Site/public/logo.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" role="img" aria-labelledby="title desc">
|
||||
<title id="title">StellaOps DevPortal</title>
|
||||
<desc id="desc">Stylised starburst mark for the StellaOps developer portal.</desc>
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
|
||||
<stop offset="0%" stop-color="#0ea5e9" />
|
||||
<stop offset="100%" stop-color="#22d3ee" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="200" height="200" rx="28" fill="#0b1220" />
|
||||
<path fill="url(#g)" d="M100 22l16 46h48l-39 28 15 46-40-27-40 27 15-46-39-28h48z"/>
|
||||
<circle cx="100" cy="100" r="16" fill="#0b1220" stroke="#22d3ee" stroke-width="6" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 679 B |
32
src/DevPortal/StellaOps.DevPortal.Site/scripts/sync-spec.mjs
Normal file
32
src/DevPortal/StellaOps.DevPortal.Site/scripts/sync-spec.mjs
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import crypto from 'node:crypto';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const moduleRoot = path.resolve(__dirname, '..');
|
||||
const repoRoot = path.resolve(moduleRoot, '..', '..', '..');
|
||||
const sourceSpec = path.join(repoRoot, 'src/Api/StellaOps.Api.OpenApi/stella.yaml');
|
||||
const targetDir = path.join(moduleRoot, 'public', 'api');
|
||||
const targetSpec = path.join(targetDir, 'stella.yaml');
|
||||
|
||||
function hashFile(filePath) {
|
||||
const hash = crypto.createHash('sha256');
|
||||
hash.update(fs.readFileSync(filePath));
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
if (!fs.existsSync(sourceSpec)) {
|
||||
console.error(`[devportal:sync-spec] missing source spec at ${sourceSpec}`);
|
||||
process.exitCode = 1;
|
||||
process.exit();
|
||||
}
|
||||
|
||||
fs.mkdirSync(targetDir, { recursive: true });
|
||||
fs.copyFileSync(sourceSpec, targetSpec);
|
||||
|
||||
const sizeKb = (fs.statSync(targetSpec).size / 1024).toFixed(1);
|
||||
const digest = hashFile(targetSpec).slice(0, 12);
|
||||
console.log(`[devportal:sync-spec] copied aggregate spec -> public/api/stella.yaml (${sizeKb} KiB, sha256:${digest}...)`);
|
||||
17
src/DevPortal/StellaOps.DevPortal.Site/src/content/config.ts
Normal file
17
src/DevPortal/StellaOps.DevPortal.Site/src/content/config.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
const docs = defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional(),
|
||||
sidebar: z
|
||||
.object({
|
||||
label: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
order: z.number().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { docs };
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
title: API Reference
|
||||
description: Aggregate OpenAPI surface for StellaOps services with schema-first navigation.
|
||||
---
|
||||
|
||||
import 'rapidoc/dist/rapidoc-min.js';
|
||||
|
||||
> The aggregate spec is composed from per-service OpenAPI files and namespaced by service (e.g., `/authority/...`). The bundled copy lives at `/api/stella.yaml` so offline builds stay self-contained.
|
||||
|
||||
<rapi-doc
|
||||
spec-url="/api/stella.yaml"
|
||||
render-style="read"
|
||||
theme="dark"
|
||||
bg-color="#0b1220"
|
||||
text-color="#e5e7eb"
|
||||
primary-color="#0ea5e9"
|
||||
nav-bg-color="#0f172a"
|
||||
nav-text-color="#cbd5e1"
|
||||
show-header="false"
|
||||
allow-try="false"
|
||||
allow-spec-url-load="false"
|
||||
allow-spec-file-load="false"
|
||||
regular-font="Space Grotesk"
|
||||
mono-font="JetBrains Mono"
|
||||
schema-style="tree"
|
||||
default-schema-tab="schema"
|
||||
sort-tags="true"
|
||||
sort-endpoints-by="path"
|
||||
hide-schema-titles="false"
|
||||
layout="row"
|
||||
style="height: 80vh; border: 1px solid #1f2937; border-radius: 12px;"
|
||||
></rapi-doc>
|
||||
|
||||
## What to look for
|
||||
- Per-operation `x-service` and `x-original-path` values expose provenance.
|
||||
- Shared schemas live under `#/components/schemas` with namespaced keys.
|
||||
- Servers list includes one entry per service; sandbox URLs will be added alongside prod.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Getting Started
|
||||
description: Build and preview the DevPortal locally with deterministic inputs.
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
- Node.js 18.18 or later (offline-friendly install).
|
||||
- `npm install --package-lock-only` to capture the lockfile; `npm ci --progress=false` when you need a full install.
|
||||
- Aggregate OpenAPI file at `src/Api/StellaOps.Api.OpenApi/stella.yaml` (generated via `npm run api:compose` from the repo root).
|
||||
|
||||
## Build locally
|
||||
1. Sync the aggregate spec into the portal assets:
|
||||
```bash
|
||||
npm run sync:spec
|
||||
```
|
||||
2. Install dependencies (skips network analytics):
|
||||
```bash
|
||||
npm ci --ignore-scripts --progress=false --no-fund --no-audit
|
||||
```
|
||||
3. Run the site locally:
|
||||
```bash
|
||||
npm run dev -- --host
|
||||
```
|
||||
4. Generate a production bundle (offline-ready):
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Determinism & offline posture
|
||||
- The portal never pulls fonts or JS from CDNs; all assets live under `public/`.
|
||||
- The aggregate spec is stored at `/api/stella.yaml` and is bundled into exports.
|
||||
- Search uses a local index generated at build time—no third-party calls.
|
||||
|
||||
## Where things live
|
||||
- Content: `src/content/docs/**`
|
||||
- Styling tokens: `src/styles/custom.css`
|
||||
- Spec sync helper: `scripts/sync-spec.mjs`
|
||||
- Build output: `dist/` (ready for static serving or offline export)
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: Navigation & Search
|
||||
description: How the DevPortal organizes content and builds offline search indices.
|
||||
---
|
||||
|
||||
## Navigation model
|
||||
- **Overview** for narrative journeys and onboarding.
|
||||
- **API** for the aggregate OpenAPI viewer and schema-aware tools.
|
||||
- **Roadmap** for release notes and drop-specific changes.
|
||||
- Sidebar order is pinned in `astro.config.mjs` to keep builds deterministic.
|
||||
|
||||
## Search
|
||||
- Provider: **local** (FlexSearch) generated at build time.
|
||||
- Works offline; indexes titles, headings, and descriptions across docs.
|
||||
- Search box appears in the top nav. Keyboard shortcut: `/` (press in any page).
|
||||
|
||||
## Content guidelines
|
||||
- Every page must declare `title` and `description` frontmatter to land in the index.
|
||||
- Prefer short headings (≤60 characters) for clean search snippets.
|
||||
- Keep code examples deterministic: pin versions and avoid network calls.
|
||||
|
||||
## Upcoming
|
||||
- API operation deep-links will join the index once schema viewer (DEVPORT-62-002) lands.
|
||||
- Try-It console (DEVPORT-63-001) will expose a sandbox surface gated by scopes.
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Welcome to the StellaOps DevPortal
|
||||
description: Deterministic, offline-first documentation and API reference for the StellaOps platform.
|
||||
---
|
||||
|
||||
import { Card, CardGrid } from '@astrojs/starlight/components';
|
||||
|
||||
The StellaOps DevPortal binds specs, runnable examples, and SDK entrypoints into a single, deterministic build. Everything here is designed to work online or fully air-gapped so auditors and engineers see the same evidence.
|
||||
|
||||
<CardGrid>
|
||||
<Card title="Aggregate API" icon="tabler:api" href="/docs/api-reference/">
|
||||
Browse the composed OpenAPI surface, schema-first paths, and auth expectations.
|
||||
</Card>
|
||||
<Card title="Get started" icon="tabler:flag" href="/docs/guides/getting-started/">
|
||||
Install tooling, sync the aggregate spec, and render the portal locally.
|
||||
</Card>
|
||||
<Card title="Navigation & search" icon="tabler:search" href="/docs/guides/navigation-search/">
|
||||
Learn how content is organized and how offline search works.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
## Why now
|
||||
- Offline parity: the same portal ships as static HTML with bundled assets.
|
||||
- Deterministic rebuilds: aggregate spec and examples are pinned in-source.
|
||||
- Audit-ready: schema-first views, provenance attached to specs, and upcoming try-it sandbox.
|
||||
|
||||
## What lives here
|
||||
- Aggregate OpenAPI (namespaced by service) with schema explorer.
|
||||
- Guides for tokens, scopes, SDKs, and export bundles.
|
||||
- Release notes aligned to platform drops.
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Release Notes
|
||||
description: Drop-by-drop updates for the DevPortal surface.
|
||||
---
|
||||
|
||||
## 2025-11 (Sprint 0206.0001.0001)
|
||||
- ✅ Selected Astro + Starlight as the static site generator for deterministic offline builds.
|
||||
- ✅ Added navigation scaffolding (Overview, Guides, API, Roadmap) with local search enabled.
|
||||
- ✅ Embedded aggregate OpenAPI via RapiDoc using bundled `/api/stella.yaml`.
|
||||
- 🔜 Schema explorer UI and copy-curl snippets (DEVPORT-62-002).
|
||||
- 🔜 Try-It console against sandbox scopes (DEVPORT-63-001).
|
||||
|
||||
## How to contribute release entries
|
||||
- Add a dated section with bullet points grouped by task ID when features land.
|
||||
- Keep entries aligned to sprint IDs and include any risks or follow-ups.
|
||||
2
src/DevPortal/StellaOps.DevPortal.Site/src/env.d.ts
vendored
Normal file
2
src/DevPortal/StellaOps.DevPortal.Site/src/env.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/// <reference path="../.astro/types.d.ts" />
|
||||
/// <reference types="astro/client" />
|
||||
45
src/DevPortal/StellaOps.DevPortal.Site/src/styles/custom.css
Normal file
45
src/DevPortal/StellaOps.DevPortal.Site/src/styles/custom.css
Normal file
@@ -0,0 +1,45 @@
|
||||
:root {
|
||||
--sl-font-sans: "Space Grotesk", "Segoe UI", "Inter", system-ui, -apple-system, sans-serif;
|
||||
--sl-font-mono: "JetBrains Mono", "SFMono-Regular", ui-monospace, Menlo, Consolas, monospace;
|
||||
--sl-color-accent: #0ea5e9;
|
||||
--sl-color-text: #e5e7eb;
|
||||
--sl-color-text-accent: #a5f3fc;
|
||||
--sl-color-text-muted: #cbd5e1;
|
||||
--sl-color-bg: #0b1220;
|
||||
--sl-color-bg-soft: #0f172a;
|
||||
--sl-color-hairline: #1f2937;
|
||||
--sl-heading-font-weight: 700;
|
||||
--sl-body-font-weight: 400;
|
||||
}
|
||||
|
||||
body {
|
||||
background: radial-gradient(circle at 20% 20%, rgba(14, 165, 233, 0.12), transparent 25%),
|
||||
radial-gradient(circle at 80% 10%, rgba(99, 102, 241, 0.14), transparent 25%),
|
||||
linear-gradient(180deg, #0b1220 0%, #0f172a 60%, #0b1220 100%);
|
||||
color: var(--sl-color-text);
|
||||
}
|
||||
|
||||
.sl-link-card {
|
||||
border: 1px solid var(--sl-color-hairline);
|
||||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), rgba(255, 255, 255, 0.01));
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
:where(.sl-markdown) h2 {
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
:where(.sl-markdown) code {
|
||||
background: rgba(15, 23, 42, 0.7);
|
||||
border: 1px solid var(--sl-color-hairline);
|
||||
}
|
||||
|
||||
nav.sl-topnav {
|
||||
border-bottom: 1px solid var(--sl-color-hairline);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.sl-search-box input {
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
border: 1px solid var(--sl-color-hairline);
|
||||
}
|
||||
7
src/DevPortal/StellaOps.DevPortal.Site/tsconfig.json
Normal file
7
src/DevPortal/StellaOps.DevPortal.Site/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"types": ["astro/client"],
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user