@fulmenhq/tsfulmen 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +241 -4
- package/config/crucible-ts/devsecops/lorage-central/activity/v1.0.0/defaults.yaml +19 -0
- package/config/crucible-ts/devsecops/lorage-central/credentials/v1.0.0/defaults.yaml +21 -0
- package/config/crucible-ts/devsecops/lorage-central/policy/v1.0.0/defaults.yaml +36 -0
- package/config/crucible-ts/devsecops/lorage-central/recipe/v1.0.0/defaults.yaml +61 -0
- package/config/crucible-ts/devsecops/lorage-central/runbooks/v1.0.0/defaults.yaml +50 -0
- package/config/crucible-ts/devsecops/lorage-central/tenant/v1.0.0/defaults.yaml +28 -0
- package/config/crucible-ts/devsecops/secrets/v1.0.0/defaults.yaml +198 -0
- package/config/crucible-ts/library/fulpack/fixtures/README.md +157 -0
- package/config/crucible-ts/library/fulpack/fixtures/basic.tar +0 -0
- package/config/crucible-ts/library/fulpack/fixtures/basic.tar.gz +0 -0
- package/config/crucible-ts/library/fulpack/fixtures/basic.tar.gz.txt +19 -0
- package/config/crucible-ts/library/fulpack/fixtures/basic.tar.txt +54 -0
- package/config/crucible-ts/library/fulpack/fixtures/nested.zip +0 -0
- package/config/crucible-ts/library/fulpack/fixtures/nested.zip.txt +24 -0
- package/config/crucible-ts/library/fulpack/fixtures/pathological.tar.gz +0 -0
- package/config/crucible-ts/library/fulpack/fixtures/pathological.tar.gz.txt +49 -0
- package/config/crucible-ts/taxonomy/devsecops/auth-methods.yaml +34 -0
- package/config/crucible-ts/taxonomy/devsecops/geo.yaml +54 -0
- package/config/crucible-ts/taxonomy/devsecops/infra-phases.yaml +43 -0
- package/config/crucible-ts/taxonomy/devsecops/infra-providers.yaml +97 -0
- package/config/crucible-ts/taxonomy/devsecops/modules/v1.0.0/modules.yaml +46 -0
- package/config/crucible-ts/taxonomy/library/foundry-catalogs/v1.0.0/catalogs.yaml +55 -0
- package/config/crucible-ts/taxonomy/library/platform-modules/v1.0.0/modules.yaml +591 -0
- package/config/crucible-ts/taxonomy/metrics.yaml +1 -1
- package/config/crucible-ts/taxonomy/repository-categories.yaml +53 -45
- package/dist/appidentity/index.d.ts +2 -2
- package/dist/appidentity/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js.map +1 -1
- package/dist/crucible/index.d.ts +3 -3
- package/dist/crucible/index.js.map +1 -1
- package/dist/docscribe/index.d.ts +1 -1
- package/dist/docscribe/index.js.map +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/foundry/index.d.ts +14 -14
- package/dist/foundry/index.js.map +1 -1
- package/dist/foundry/similarity/index.d.ts +2 -2
- package/dist/foundry/similarity/index.js.map +1 -1
- package/dist/fulhash/index.js.map +1 -1
- package/dist/fulpack/index.d.ts +324 -0
- package/dist/fulpack/index.js +1505 -0
- package/dist/fulpack/index.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1508 -10
- package/dist/index.js.map +1 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/pathfinder/index.d.ts +178 -5
- package/dist/pathfinder/index.js +189 -18
- package/dist/pathfinder/index.js.map +1 -1
- package/dist/{registry-BoDv4iHO.d.ts → registry-n88udrCm.d.ts} +2 -2
- package/dist/schema/index.d.ts +3 -3
- package/dist/schema/index.js.map +1 -1
- package/dist/{suggest-CLqjLZ5L.d.ts → suggest-Cv7SVQRu.d.ts} +2 -2
- package/dist/telemetry/index.d.ts +3 -3
- package/dist/telemetry/index.js.map +1 -1
- package/dist/{types-B_WtvQbS.d.ts → types-BJswWpQC.d.ts} +7 -7
- package/package.json +10 -1
- package/schemas/crucible-ts/devsecops/lorage-central/activity/v1.0.0/README.md +104 -0
- package/schemas/crucible-ts/devsecops/lorage-central/activity/v1.0.0/activity.schema.json +118 -0
- package/schemas/crucible-ts/devsecops/lorage-central/credentials/v1.0.0/README.md +100 -0
- package/schemas/crucible-ts/devsecops/lorage-central/credentials/v1.0.0/credentials.schema.json +123 -0
- package/schemas/crucible-ts/devsecops/lorage-central/policy/v1.0.0/README.md +112 -0
- package/schemas/crucible-ts/devsecops/lorage-central/policy/v1.0.0/policy.schema.json +197 -0
- package/schemas/crucible-ts/devsecops/lorage-central/recipe/v1.0.0/README.md +203 -0
- package/schemas/crucible-ts/devsecops/lorage-central/recipe/v1.0.0/recipe.schema.json +353 -0
- package/schemas/crucible-ts/devsecops/lorage-central/runbooks/v1.0.0/README.md +280 -0
- package/schemas/crucible-ts/devsecops/lorage-central/runbooks/v1.0.0/runbook.schema.json +216 -0
- package/schemas/crucible-ts/devsecops/lorage-central/tenant/v1.0.0/README.md +84 -0
- package/schemas/crucible-ts/devsecops/lorage-central/tenant/v1.0.0/tenant.schema.json +131 -0
- package/schemas/crucible-ts/devsecops/secrets/v1.0.0/secrets.schema.json +250 -0
- package/schemas/crucible-ts/library/fulencode/v1.0.0/fulencode-config.schema.json +90 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/archive-entry.schema.json +61 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/archive-info.schema.json +75 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/archive-manifest.schema.json +112 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/create-options.schema.json +53 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/extract-options.schema.json +49 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/extract-result.schema.json +54 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/scan-options.schema.json +42 -0
- package/schemas/crucible-ts/library/fulpack/v1.0.0/validation-result.schema.json +58 -0
- package/schemas/crucible-ts/observability/logging/v1.0.0/logger-config.schema.json +1 -30
- package/schemas/crucible-ts/taxonomy/devsecops/auth-methods/v1.0.0/README.md +47 -0
- package/schemas/crucible-ts/taxonomy/devsecops/auth-methods/v1.0.0/auth-methods-key.schema.json +16 -0
- package/schemas/crucible-ts/taxonomy/devsecops/auth-methods/v1.0.0/auth-methods-metadata.schema.json +49 -0
- package/schemas/crucible-ts/taxonomy/devsecops/geo/v1.0.0/README.md +63 -0
- package/schemas/crucible-ts/taxonomy/devsecops/geo/v1.0.0/geo-key.schema.json +31 -0
- package/schemas/crucible-ts/taxonomy/devsecops/geo/v1.0.0/geo-metadata.schema.json +104 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-phases/v1.0.0/README.md +48 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-phases/v1.0.0/infra-phases-key.schema.json +17 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-phases/v1.0.0/infra-phases-metadata.schema.json +53 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-providers/v1.0.0/README.md +73 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-providers/v1.0.0/infra-providers-key.schema.json +18 -0
- package/schemas/crucible-ts/taxonomy/devsecops/infra-providers/v1.0.0/infra-providers-metadata.schema.json +77 -0
- package/schemas/crucible-ts/taxonomy/devsecops/modules/v1.0.0/devsecops-module-entry.schema.json +117 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/detection-confidence/v1.0.0/levels.schema.json +253 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/detection-confidence/v1.0.0/levels.yaml +167 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/encoding-families/v1.0.0/families.schema.json +184 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/encoding-families/v1.0.0/families.yaml +142 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/normalization-profiles/v1.0.0/profiles.schema.json +253 -0
- package/schemas/crucible-ts/taxonomy/library/fulencode/normalization-profiles/v1.0.0/profiles.yaml +173 -0
- package/schemas/crucible-ts/taxonomy/library/fulpack/archive-formats/v1.0.0/formats.yaml +86 -0
- package/schemas/crucible-ts/taxonomy/library/fulpack/entry-types/v1.0.0/types.yaml +18 -0
- package/schemas/crucible-ts/taxonomy/library/fulpack/operations/v1.0.0/operations.yaml +36 -0
- package/schemas/crucible-ts/taxonomy/library/modules/v1.0.0/README.md +86 -0
- package/schemas/crucible-ts/taxonomy/library/modules/v1.0.0/module-entry.schema.json +408 -0
- package/schemas/crucible-ts/taxonomy/repository-category/v1.0.0/category-key.schema.json +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,44 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Fulpack Module** (`@fulmenhq/tsfulmen/fulpack`) - Security-first archive operations for TAR, TAR.GZ, ZIP, and GZIP formats
|
|
13
|
+
- **Five Canonical Operations**:
|
|
14
|
+
- `create()` - Create archives from files/directories with configurable compression
|
|
15
|
+
- `extract()` - Extract archives with comprehensive security checks
|
|
16
|
+
- `scan()` - List archive contents without extraction (Pathfinder integration backend)
|
|
17
|
+
- `verify()` - Validate archive integrity and security before extraction
|
|
18
|
+
- `info()` - Get quick archive metadata (format, size, compression ratio)
|
|
19
|
+
- **Security-First Design**:
|
|
20
|
+
- Path traversal protection (rejects `../` and absolute paths)
|
|
21
|
+
- Decompression bomb detection (size/ratio/entry count limits)
|
|
22
|
+
- Symlink safety validation (prevents directory escapes)
|
|
23
|
+
- Checksum verification via fulhash integration (SHA-256, xxh3-128)
|
|
24
|
+
- **Four Archive Formats**:
|
|
25
|
+
- TAR (uncompressed) - Maximum speed for pre-compressed data
|
|
26
|
+
- TAR.GZ (gzip) - General purpose with best compatibility
|
|
27
|
+
- ZIP (deflate) - Windows compatibility and random access
|
|
28
|
+
- GZIP - Single file compression
|
|
29
|
+
- **Pathfinder Integration**: `scan()` serves as backend for archive discovery
|
|
30
|
+
- **Comprehensive Documentation**: Full API reference, security guide, format selection guide, and usage examples
|
|
31
|
+
- **Test Coverage**: 20 tests covering all operations and security checks
|
|
32
|
+
- **Error Handling**: Structured `FulpackOperationError` with operation context and security violation details
|
|
33
|
+
|
|
34
|
+
- **Pathfinder Repository Root Discovery** (`findRepositoryRoot`) - Secure upward traversal to find repository markers
|
|
35
|
+
- **Security-First Design**:
|
|
36
|
+
- Boundary enforcement (home directory/explicit/filesystem root)
|
|
37
|
+
- Max depth limiting (default 10 levels)
|
|
38
|
+
- Symlink loop detection (opt-in with `followSymlinks=true`)
|
|
39
|
+
- Path constraint validation for workspace boundaries
|
|
40
|
+
- Cross-platform support (POSIX root, Windows drives, UNC paths)
|
|
41
|
+
- **Predefined Marker Sets**: GitMarkers, NodeMarkers, PythonMarkers, GoModMarkers, MonorepoMarkers
|
|
42
|
+
- **Flexible Search**: Stop at first marker (default) or find deepest (monorepo root)
|
|
43
|
+
- **Helper Functions**: `withMaxDepth`, `withBoundary`, `withStopAtFirst`, `withConstraint`, `withFollowSymlinks`
|
|
44
|
+
- **Comprehensive Errors**: Structured errors with codes (REPOSITORY_NOT_FOUND, INVALID_BOUNDARY, TRAVERSAL_LOOP, etc.)
|
|
45
|
+
- **Test Coverage**: 26 tests covering security, boundary enforcement, and cross-platform behavior
|
|
46
|
+
- **Complete Documentation**: Full pathfinder README with API reference, safe usage patterns, and migration guide
|
|
47
|
+
|
|
10
48
|
---
|
|
11
49
|
|
|
12
50
|
## [0.1.8] - 2025-11-08
|
package/README.md
CHANGED
|
@@ -9,10 +9,10 @@ TypeScript Fulmen helper library for enterprise-scale development.
|
|
|
9
9
|
## Status
|
|
10
10
|
|
|
11
11
|
**Lifecycle Phase:** `alpha` (see [`LIFECYCLE_PHASE`](LIFECYCLE_PHASE))
|
|
12
|
-
**Development Status:** ✅ v0.1.
|
|
13
|
-
**Test Coverage:**
|
|
12
|
+
**Development Status:** ✅ v0.1.9 - Fulpack archives, pathfinder repository root discovery
|
|
13
|
+
**Test Coverage:** 1638 tests passing (100% pass rate)
|
|
14
14
|
|
|
15
|
-
TSFulmen v0.1.
|
|
15
|
+
TSFulmen v0.1.9 adds security-first archive operations (fulpack) for TAR/TAR.GZ/ZIP/GZIP formats and repository root discovery (pathfinder) with boundary enforcement. See [TSFulmen Overview](docs/tsfulmen_overview.md) for roadmap.
|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -20,6 +20,7 @@ TSFulmen v0.1.5 adds cross-platform signal handling with graceful shutdown patte
|
|
|
20
20
|
- ✅ **Telemetry & Metrics** - Counter/gauge/histogram with OTLP export (85 tests)
|
|
21
21
|
- ✅ **Telemetry Instrumentation** - Metrics in config, schema, crucible modules (24 tests)
|
|
22
22
|
- ✅ **FulHash** - Fast hashing with XXH3-128 and SHA-256, 22x faster small inputs (157 tests)
|
|
23
|
+
- ✅ **Fulpack** - Archive operations (TAR, TAR.GZ, ZIP, GZIP) with security-first design (20 tests)
|
|
23
24
|
- ✅ **Progressive Logging** - Policy enforcement with Pino profiles (83 tests)
|
|
24
25
|
- ✅ **Crucible Shim** - Typed access to synced schemas, docs, and config defaults (96 tests)
|
|
25
26
|
- ✅ **DocScribe** - Document processing with frontmatter parsing (50+ tests)
|
|
@@ -29,7 +30,7 @@ TSFulmen v0.1.5 adds cross-platform signal handling with graceful shutdown patte
|
|
|
29
30
|
- ✅ **Exit Codes** - Standardized process exit codes with simplified modes and platform detection (34 tests)
|
|
30
31
|
- ✅ **Signal Handling** - Cross-platform signal handling with graceful shutdown and Windows fallback (180 tests)
|
|
31
32
|
- ✅ **Application Identity** - .fulmen/app.yaml discovery with caching and validation (93 tests)
|
|
32
|
-
- ✅ **Pathfinder** - Filesystem traversal with
|
|
33
|
+
- ✅ **Pathfinder** - Filesystem traversal, repository root discovery with security boundaries, checksums, and observability (70 tests)
|
|
33
34
|
- 🚧 **Three-Layer Config Loading** - Defaults → User → BYOC (planned v0.2.x)
|
|
34
35
|
|
|
35
36
|
## Installation
|
|
@@ -108,6 +109,8 @@ src/
|
|
|
108
109
|
├── crucible/ # 🚧 Crucible SSOT shim
|
|
109
110
|
├── errors/ # ✅ Error handling & propagation
|
|
110
111
|
├── foundry/ # ✅ Pattern catalogs, HTTP statuses, MIME detection
|
|
112
|
+
├── fulhash/ # ✅ Fast hashing with XXH3-128 and SHA-256
|
|
113
|
+
├── fulpack/ # ✅ Archive operations (TAR, TAR.GZ, ZIP, GZIP)
|
|
111
114
|
├── logging/ # ✅ Progressive logging with policy enforcement
|
|
112
115
|
├── pathfinder/ # ✅ Filesystem traversal with checksums and observability
|
|
113
116
|
├── schema/ # ✅ Schema validation (AJV + CLI)
|
|
@@ -515,6 +518,240 @@ const type = await detectMimeType(buffer, {
|
|
|
515
518
|
});
|
|
516
519
|
```
|
|
517
520
|
|
|
521
|
+
### Fulpack - Archive Operations
|
|
522
|
+
|
|
523
|
+
Secure archive creation, extraction, and inspection with security-first design for TAR, TAR.GZ, ZIP, and GZIP formats.
|
|
524
|
+
|
|
525
|
+
**Features:**
|
|
526
|
+
|
|
527
|
+
- Five canonical operations: `create()`, `extract()`, `scan()`, `verify()`, `info()`
|
|
528
|
+
- Four archive formats: TAR (uncompressed), TAR.GZ (gzip), ZIP (deflate), GZIP (single file)
|
|
529
|
+
- Security-first design: path traversal protection, decompression bomb detection, symlink safety validation
|
|
530
|
+
- Checksum verification via fulhash integration (SHA-256, xxh3-128)
|
|
531
|
+
- Pathfinder integration: `scan()` backend for archive discovery
|
|
532
|
+
- Streaming architecture for memory-efficient operations
|
|
533
|
+
|
|
534
|
+
**Basic Usage:**
|
|
535
|
+
|
|
536
|
+
```typescript
|
|
537
|
+
import {
|
|
538
|
+
create,
|
|
539
|
+
extract,
|
|
540
|
+
scan,
|
|
541
|
+
verify,
|
|
542
|
+
info,
|
|
543
|
+
ArchiveFormat,
|
|
544
|
+
} from "@fulmenhq/tsfulmen/fulpack";
|
|
545
|
+
|
|
546
|
+
// Create TAR.GZ archive
|
|
547
|
+
const archiveInfo = await create(
|
|
548
|
+
"./src", // Source directory
|
|
549
|
+
"./dist/app.tar.gz", // Output archive
|
|
550
|
+
ArchiveFormat.TAR_GZ, // Format
|
|
551
|
+
{ compression_level: 9 }, // Options
|
|
552
|
+
);
|
|
553
|
+
|
|
554
|
+
// Extract archive with security checks
|
|
555
|
+
const result = await extract(
|
|
556
|
+
"./dist/app.tar.gz", // Archive path
|
|
557
|
+
"./output", // Destination
|
|
558
|
+
{ overwrite: "skip" }, // Skip existing files
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
console.log(
|
|
562
|
+
`Extracted ${result.extracted_count} files, skipped ${result.skipped_count}`,
|
|
563
|
+
);
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**Scan Archives (Pathfinder Integration):**
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
// Scan archive contents without extraction
|
|
570
|
+
const entries = await scan("./data.tar.gz");
|
|
571
|
+
|
|
572
|
+
// Filter entries using standard JavaScript
|
|
573
|
+
const csvFiles = entries.filter(
|
|
574
|
+
(e) => e.type === "file" && e.path.endsWith(".csv"),
|
|
575
|
+
);
|
|
576
|
+
console.log(`Found ${csvFiles.length} CSV files`);
|
|
577
|
+
|
|
578
|
+
// Check for specific files
|
|
579
|
+
const hasConfig = entries.some((e) => e.path === "config/app.json");
|
|
580
|
+
|
|
581
|
+
// Get total uncompressed size
|
|
582
|
+
const totalSize = entries.reduce((sum, e) => sum + e.size, 0);
|
|
583
|
+
console.log(`Total size: ${(totalSize / 1024 / 1024).toFixed(2)} MB`);
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Security Validation:**
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
// Verify archive integrity before extraction
|
|
590
|
+
const validation = await verify("./untrusted.tar.gz");
|
|
591
|
+
|
|
592
|
+
if (!validation.valid) {
|
|
593
|
+
console.error("Archive validation failed:");
|
|
594
|
+
validation.errors.forEach((err) =>
|
|
595
|
+
console.error(` - ${err.code}: ${err.message}`),
|
|
596
|
+
);
|
|
597
|
+
process.exit(1);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Check security validations performed
|
|
601
|
+
console.log("Security checks:", validation.checks_performed.join(", "));
|
|
602
|
+
// Output: structure_valid, no_path_traversal, symlinks_safe, no_decompression_bomb
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Archive Metadata:**
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
// Get quick metadata without extraction
|
|
609
|
+
const metadata = await info("./backup.tar.gz");
|
|
610
|
+
|
|
611
|
+
console.log(`Format: ${metadata.format}`);
|
|
612
|
+
console.log(`Entries: ${metadata.entry_count}`);
|
|
613
|
+
console.log(
|
|
614
|
+
`Compressed: ${(metadata.compressed_size / 1024 / 1024).toFixed(2)} MB`,
|
|
615
|
+
);
|
|
616
|
+
console.log(
|
|
617
|
+
`Uncompressed: ${(metadata.total_size / 1024 / 1024).toFixed(2)} MB`,
|
|
618
|
+
);
|
|
619
|
+
console.log(`Ratio: ${metadata.compression_ratio.toFixed(2)}:1`);
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
**Format Selection:**
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
// TAR (uncompressed) - Fastest for pre-compressed data
|
|
626
|
+
await create("./images", "./backup.tar", ArchiveFormat.TAR);
|
|
627
|
+
|
|
628
|
+
// TAR.GZ - General purpose, best compatibility
|
|
629
|
+
await create("./src", "./release.tar.gz", ArchiveFormat.TAR_GZ, {
|
|
630
|
+
compression_level: 9,
|
|
631
|
+
exclude_patterns: ["**/*.test.ts", "**/node_modules/**"],
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// ZIP - Windows compatibility, random access
|
|
635
|
+
await create(["./config", "./scripts"], "./deploy.zip", ArchiveFormat.ZIP);
|
|
636
|
+
|
|
637
|
+
// GZIP - Single file compression
|
|
638
|
+
await create("./large-data.csv", "./large-data.csv.gz", ArchiveFormat.GZIP);
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### Pathfinder - Repository Root Discovery
|
|
642
|
+
|
|
643
|
+
Find repository markers (`.git`, `package.json`, etc.) by walking up the directory tree with security-first design, boundary enforcement, and comprehensive error handling.
|
|
644
|
+
|
|
645
|
+
**Features:**
|
|
646
|
+
|
|
647
|
+
- Security-first design with boundary enforcement (home directory/explicit/filesystem root ceilings)
|
|
648
|
+
- Max depth limiting (default 10 levels) to prevent excessive traversal
|
|
649
|
+
- Symlink loop detection with opt-in following
|
|
650
|
+
- Path constraint validation for workspace boundaries
|
|
651
|
+
- Cross-platform support (POSIX root, Windows drives, UNC paths)
|
|
652
|
+
- Predefined marker sets for common ecosystems (Git, Node, Python, Go, Monorepo)
|
|
653
|
+
- Structured errors with context for debugging
|
|
654
|
+
|
|
655
|
+
**Basic Usage:**
|
|
656
|
+
|
|
657
|
+
```typescript
|
|
658
|
+
import {
|
|
659
|
+
findRepositoryRoot,
|
|
660
|
+
GitMarkers,
|
|
661
|
+
NodeMarkers,
|
|
662
|
+
} from "@fulmenhq/tsfulmen/pathfinder";
|
|
663
|
+
|
|
664
|
+
// Find Git repository root from current directory
|
|
665
|
+
const gitRoot = await findRepositoryRoot(process.cwd(), GitMarkers);
|
|
666
|
+
console.log(`Git root: ${gitRoot}`);
|
|
667
|
+
|
|
668
|
+
// Find Node.js project root
|
|
669
|
+
const nodeRoot = await findRepositoryRoot("./src/components", NodeMarkers);
|
|
670
|
+
console.log(`Node root: ${nodeRoot}`);
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**Predefined Marker Sets:**
|
|
674
|
+
|
|
675
|
+
```typescript
|
|
676
|
+
import {
|
|
677
|
+
GitMarkers, // [".git"]
|
|
678
|
+
NodeMarkers, // ["package.json", "package-lock.json"]
|
|
679
|
+
PythonMarkers, // ["pyproject.toml", "setup.py", "requirements.txt", "Pipfile"]
|
|
680
|
+
GoModMarkers, // ["go.mod"]
|
|
681
|
+
MonorepoMarkers, // ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"]
|
|
682
|
+
} from "@fulmenhq/tsfulmen/pathfinder";
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
**Security Boundaries:**
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
import {
|
|
689
|
+
ConstraintType,
|
|
690
|
+
EnforcementLevel,
|
|
691
|
+
} from "@fulmenhq/tsfulmen/pathfinder";
|
|
692
|
+
|
|
693
|
+
// Secure search within project boundary
|
|
694
|
+
const root = await findRepositoryRoot("./src/components", GitMarkers, {
|
|
695
|
+
boundary: "/home/user/projects/myapp", // Don't search above project
|
|
696
|
+
constraint: {
|
|
697
|
+
root: "/home/user/projects", // Enforce workspace constraint
|
|
698
|
+
type: ConstraintType.WORKSPACE,
|
|
699
|
+
enforcementLevel: EnforcementLevel.STRICT,
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
**Monorepo Support:**
|
|
705
|
+
|
|
706
|
+
```typescript
|
|
707
|
+
// Find deepest marker (closest to filesystem root) for monorepo roots
|
|
708
|
+
// Directory: /monorepo/.git and /monorepo/packages/app/.git
|
|
709
|
+
|
|
710
|
+
// stopAtFirst=true (default) - finds /monorepo/packages/app
|
|
711
|
+
const packageRoot = await findRepositoryRoot(
|
|
712
|
+
"/monorepo/packages/app/src/index.ts",
|
|
713
|
+
GitMarkers,
|
|
714
|
+
);
|
|
715
|
+
|
|
716
|
+
// stopAtFirst=false - finds /monorepo (deepest/monorepo root)
|
|
717
|
+
const monorepoRoot = await findRepositoryRoot(
|
|
718
|
+
"/monorepo/packages/app/src/index.ts",
|
|
719
|
+
GitMarkers,
|
|
720
|
+
{ stopAtFirst: false },
|
|
721
|
+
);
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**Error Handling:**
|
|
725
|
+
|
|
726
|
+
```typescript
|
|
727
|
+
import { PathfinderErrorCode } from "@fulmenhq/tsfulmen/pathfinder";
|
|
728
|
+
|
|
729
|
+
try {
|
|
730
|
+
const root = await findRepositoryRoot("./src", GitMarkers);
|
|
731
|
+
console.log(`Found: ${root}`);
|
|
732
|
+
} catch (error) {
|
|
733
|
+
if (error.data?.code === PathfinderErrorCode.REPOSITORY_NOT_FOUND) {
|
|
734
|
+
console.error("No repository marker found");
|
|
735
|
+
console.error(`Searched from: ${error.data.context.startPath}`);
|
|
736
|
+
console.error(`Max depth: ${error.data.context.maxDepth}`);
|
|
737
|
+
} else if (error.data?.code === PathfinderErrorCode.TRAVERSAL_LOOP) {
|
|
738
|
+
console.error("Cyclic symlink detected:", error.data.context);
|
|
739
|
+
} else {
|
|
740
|
+
throw error; // Re-throw unexpected errors
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
**Default Behavior:**
|
|
746
|
+
|
|
747
|
+
- **`maxDepth`**: `10` - Prevents excessive traversal
|
|
748
|
+
- **`boundary`**: User home directory (if start path under home), otherwise filesystem root
|
|
749
|
+
- **`stopAtFirst`**: `true` - Returns first marker found (closest to start path)
|
|
750
|
+
- **`followSymlinks`**: `false` - Security: symlinks not followed by default
|
|
751
|
+
- **`constraint`**: `undefined` - No additional path constraints
|
|
752
|
+
|
|
753
|
+
See [Pathfinder README](src/pathfinder/README.md) for complete API documentation.
|
|
754
|
+
|
|
518
755
|
### Pathfinder - Filesystem Discovery
|
|
519
756
|
|
|
520
757
|
Enterprise filesystem traversal with pattern matching, ignore files, optional checksums, and comprehensive observability.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/activity/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Activity Record Defaults
|
|
3
|
+
# Description: Default audit config (e.g., event templates; emitted auto).
|
|
4
|
+
# Rationale: Structured logging defaults; retain per policy.audit.
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; integrates gofulmen).
|
|
6
|
+
# Example Event Template (auto-populated in REPL)
|
|
7
|
+
eventTemplate:
|
|
8
|
+
eventType: unlock # From enum
|
|
9
|
+
outcome: success
|
|
10
|
+
metadata:
|
|
11
|
+
sessionId: "sess-default-001"
|
|
12
|
+
userId: "user-anon-123"
|
|
13
|
+
duration: "5s"
|
|
14
|
+
details: {method: totp}
|
|
15
|
+
backend: # Refs policy.audit
|
|
16
|
+
level: structured
|
|
17
|
+
retain: 30d
|
|
18
|
+
# Usage: REPL emits: {id: evt-default-unlock-001, timestamp: now, tenant: tnt-uuid-123-prod-us, ...}
|
|
19
|
+
# Stored in audit backend (e.g., Turso table); no defaults for id/timestamp (runtime).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/credentials/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Root Credentials Defaults
|
|
3
|
+
# Description: Default metadata for root creds (e.g., bootstrap key; no values—refs only).
|
|
4
|
+
# Rationale: Secure defaults (1y expiry); used in seeding/actions.
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; backend from policy).
|
|
6
|
+
id: default-bootstrap-key
|
|
7
|
+
tenant: tnt-uuid-123-prod-us # From registry
|
|
8
|
+
type: gpg-key
|
|
9
|
+
ref: "gpg://keyring/default-bootstrap" # Opaque; decrypted at runtime
|
|
10
|
+
metadata:
|
|
11
|
+
created: "2025-11-09T12:00:00Z"
|
|
12
|
+
expires: "2026-11-09T12:00:00Z" # 1y default
|
|
13
|
+
purpose: tenant-bootstrap
|
|
14
|
+
rotation:
|
|
15
|
+
interval: 365d
|
|
16
|
+
method: manual
|
|
17
|
+
backend: # Refs policy.isolation.store
|
|
18
|
+
type: gpg-file
|
|
19
|
+
enc: true
|
|
20
|
+
# Usage: In recipe.actions or seeding: ref this for bootstrap; REPL checks expiry.
|
|
21
|
+
# Example: For Turso, type: turso-root, ref: "turso://root-auth".
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/policy/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Tenant Policy Defaults
|
|
3
|
+
# Description: Default policy for new tenants (loaded via three-layer config; overrides in .fulmen/lorage.yaml).
|
|
4
|
+
# Rationale: Secure MVP defaults (short TTL, MFA required, Turso backend); confidential example (obscure publicId).
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; auto-applies dataSensitivity guards from registry).
|
|
6
|
+
tenant: tnt-uuid-123-prod-us # Obscure publicId from registry (confidential=true; no client exposure)
|
|
7
|
+
session:
|
|
8
|
+
ttl:
|
|
9
|
+
default: 15m # Force re-unlock per session
|
|
10
|
+
ops:
|
|
11
|
+
deploy: 1h
|
|
12
|
+
query: 5m
|
|
13
|
+
seed: 30m
|
|
14
|
+
maxConcurrent: 1 # Strict isolation
|
|
15
|
+
mfa:
|
|
16
|
+
required: true # Auto-true if registry.dataSensitivity.pii=true
|
|
17
|
+
methods: [totp, webauthn] # From auth-methods taxonomy
|
|
18
|
+
fallback: cli-prompt
|
|
19
|
+
isolation:
|
|
20
|
+
store:
|
|
21
|
+
type: turso # HA default
|
|
22
|
+
conn:
|
|
23
|
+
url: "turso://default-db" # Placeholder; ref root-credentials
|
|
24
|
+
auth: {ref: "gpg://keyring/default-bootstrap"}
|
|
25
|
+
enc: false # Enable for cloud-free
|
|
26
|
+
crossAccess: false
|
|
27
|
+
geoRestrictions: [eu-west-1] # From registry.geo (e.g., EU for GDPR)
|
|
28
|
+
cloudRestrictions: [aws, doc] # From registry.cloud
|
|
29
|
+
dataSensitivityGuards:
|
|
30
|
+
pii: false # Auto-from registry; triggers mfa/geo if true
|
|
31
|
+
phi: false # Triggers enc/audit if true
|
|
32
|
+
audit:
|
|
33
|
+
level: structured # gofulmen integration
|
|
34
|
+
retain: 30d
|
|
35
|
+
# Usage: REPL loads defaults + overrides; validates against schema/registry.
|
|
36
|
+
# Example Override: For PHI tenant, set dataSensitivityGuards.phi: true → auto-enc=true.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/recipe/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Recipe Defaults
|
|
3
|
+
# Description: Default recipe config (e.g., for Mattermost MVP); loaded via three-layer.
|
|
4
|
+
# Rationale: Declarative base (components/phases); procedural actions for bootstrap.
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; refs taxonomies for provider/backend/phase).
|
|
6
|
+
name: mattermost-stack # Slug-safe
|
|
7
|
+
type: deploy
|
|
8
|
+
target:
|
|
9
|
+
provider: doc # From infra-providers
|
|
10
|
+
region: nyc3
|
|
11
|
+
backend: opentofu # From toolchains
|
|
12
|
+
components:
|
|
13
|
+
- name: postgres
|
|
14
|
+
image: postgres:15
|
|
15
|
+
phase: storage # From infra-phases (order 3)
|
|
16
|
+
ports: [5432]
|
|
17
|
+
env:
|
|
18
|
+
POSTGRES_DB: mattermost
|
|
19
|
+
secrets:
|
|
20
|
+
- ref: "gpg://keyring/acme/db-pass"
|
|
21
|
+
injectAs: POSTGRES_PASSWORD
|
|
22
|
+
dependsOn: [] # No deps for base DB
|
|
23
|
+
module: db-postgres # Tofu module
|
|
24
|
+
- name: mattermost
|
|
25
|
+
image: mattermost/mattermost-team:latest
|
|
26
|
+
phase: compute # Order 4
|
|
27
|
+
ports: [8065]
|
|
28
|
+
env:
|
|
29
|
+
MM_POSTGRES_URL: "postgres://user:pass@localhost:5432/mattermost"
|
|
30
|
+
secrets:
|
|
31
|
+
- ref: "gpg://keyring/acme/mm-secret"
|
|
32
|
+
injectAs: MM_SECRET
|
|
33
|
+
dependsOn: [postgres]
|
|
34
|
+
module: app-mattermost
|
|
35
|
+
actions:
|
|
36
|
+
- type: bootstrap
|
|
37
|
+
phase: bootstrap # Order 0; procedural for key gen
|
|
38
|
+
cmd: "gpg --gen-key --batch acme-bootstrap" # Example script
|
|
39
|
+
dependsOn: []
|
|
40
|
+
- type: script
|
|
41
|
+
phase: network # Order 2
|
|
42
|
+
cmd: "doctl compute vpc create --name acme-vpc" # SDK wrapper for VPC
|
|
43
|
+
dependsOn: [bootstrap]
|
|
44
|
+
secrets:
|
|
45
|
+
backend: gpg-keyring # Refs policy.isolation.store
|
|
46
|
+
globalRefs:
|
|
47
|
+
- ref: "turso://shared-network-key"
|
|
48
|
+
validate:
|
|
49
|
+
- type: health
|
|
50
|
+
endpoint: "http://localhost:8065/health"
|
|
51
|
+
- type: connect
|
|
52
|
+
endpoint: "postgres://localhost:5432/mattermost"
|
|
53
|
+
diff: # For seed type
|
|
54
|
+
from: v1-0
|
|
55
|
+
to: v1-1
|
|
56
|
+
changes:
|
|
57
|
+
- op: add
|
|
58
|
+
path: /entries/mm-secret
|
|
59
|
+
value: {ref: "gpg://keyring/acme/mm-secret"}
|
|
60
|
+
# Usage: REPL: lorage deploy --recipe mattermost-stack (loads defaults + overrides; topo-sorts phases/actions).
|
|
61
|
+
# Example: For Open edX, add k3s module in compute phase, network action for LB.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/runbooks/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Runbook Defaults
|
|
3
|
+
# Description: Default runbook config (e.g., global-network prototype); loaded via three-layer.
|
|
4
|
+
# Rationale: Serializes Markdown prototypes (e.g., from .plans/research/); executable in REPL.
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; refs phases/recipe for steps).
|
|
6
|
+
id: global-network # Slug-safe
|
|
7
|
+
title: Global Enterprise Network Setup
|
|
8
|
+
tenantScope: [all] # Or specific publicIds
|
|
9
|
+
description: >-
|
|
10
|
+
Beginnings of the Runbook: Global Enterprise Picture with Tenants. Our runbook will live in the IDE... (from prototypes).
|
|
11
|
+
phases:
|
|
12
|
+
- id: bootstrap # From infra-phases
|
|
13
|
+
title: Initial Setup
|
|
14
|
+
description: "Core Components: Provision monitoring first."
|
|
15
|
+
steps:
|
|
16
|
+
- id: vaultwarden-init
|
|
17
|
+
type: script
|
|
18
|
+
content: "docker run -d --name vaultwarden vaultwarden/server:latest" # Bootstrap secrets
|
|
19
|
+
dependsOn: []
|
|
20
|
+
parallel: false
|
|
21
|
+
- id: prometheus-setup
|
|
22
|
+
type: action
|
|
23
|
+
ref: prometheus-stack # Ref recipe
|
|
24
|
+
dependsOn: [vaultwarden-init]
|
|
25
|
+
- id: network # Order 2
|
|
26
|
+
title: Networking Backbone
|
|
27
|
+
description: "Zero-trust backbone (Cloudflare Gateway); VPC peering for hybrids."
|
|
28
|
+
steps:
|
|
29
|
+
- id: tenant-table
|
|
30
|
+
type: table
|
|
31
|
+
content: |
|
|
32
|
+
| Tenant | Type | Focus | Clouds (Priority) | Secrets Scope | Initial Infra Needs |
|
|
33
|
+
|--------|------|-------|-------------------|---------------|---------------------|
|
|
34
|
+
| fulmenhq | Ecosystem | Tonnerre templates | AWS/GCP (core), Cloudflare (edge), Hetzner/DO (cost-opt) | IaC vars, SDK keys | OpenTofu state backend (S3), CI/CD pipelines |
|
|
35
|
+
| 3 Leaps Sponsored | Internal | Sponsored OSS | Cloudflare (Workers/DNS), Azure (AI), Hetzner (compute) | API tokens, DB creds | Worker deployments, basic storage |
|
|
36
|
+
| 3 Leaps Commercial | External | Client-specific | Client-dictated (AWS/Azure/GCP) | Isolated vaults | Hybrid connectivity, compliance-heavy |
|
|
37
|
+
dependsOn: []
|
|
38
|
+
parallel: true # Table review parallel with setup
|
|
39
|
+
- id: vpc-peering-setup
|
|
40
|
+
type: script
|
|
41
|
+
content: "doctl compute vpc create --name global-vpc" # Create VPC for hybrid peering
|
|
42
|
+
dependsOn: [tenant-table]
|
|
43
|
+
validate:
|
|
44
|
+
type: custom
|
|
45
|
+
script: "check-vpc-connectivity.sh"
|
|
46
|
+
audit:
|
|
47
|
+
backend: postgres
|
|
48
|
+
retention: 30
|
|
49
|
+
# Usage: REPL: lorage runbook global-network --phase network (executes steps, audits).
|
|
50
|
+
# Example: From prototypes—serialize Markdown tables/scripts; future: Conditional for tenant.geo.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# config/devsecops/lorage-central/tenant/v1.0.0/defaults.yaml
|
|
2
|
+
# L'Orage Central Tenant Registry Defaults
|
|
3
|
+
# Description: Default registry for new clients/tenants (loaded via three-layer; e.g., bootstrap new client).
|
|
4
|
+
# Rationale: Confidential example (obscure publicIds); multi-tenant per client (prod/dev).
|
|
5
|
+
# Version: v1.0.0 (Ties to schema; geo/cloud from taxonomies).
|
|
6
|
+
client:
|
|
7
|
+
id: default-client-internal
|
|
8
|
+
name: Default Client # Confidential; not exposed
|
|
9
|
+
confidential: true # Obscure publicIds (UUID-based)
|
|
10
|
+
tenants:
|
|
11
|
+
- publicId: tnt-uuid-123-prod-us # Globally unique/obscure
|
|
12
|
+
purpose: production-mattermost
|
|
13
|
+
geo: [na] # From geo-regions (expands to us/ca)
|
|
14
|
+
cloud: [doc, aws] # From infra-providers
|
|
15
|
+
dataSensitivity:
|
|
16
|
+
pii: false
|
|
17
|
+
phi: false
|
|
18
|
+
other: [] # e.g., [pci-dss]
|
|
19
|
+
- publicId: tnt-uuid-456-dev-eu
|
|
20
|
+
purpose: development-testing
|
|
21
|
+
geo: [eu] # Expands to de/fr/gb/ch (conventions)
|
|
22
|
+
cloud: [gcp]
|
|
23
|
+
dataSensitivity:
|
|
24
|
+
pii: true # Triggers policy guards (mfa/geo)
|
|
25
|
+
phi: false
|
|
26
|
+
globalUniqueness: true # Enforced (UUID for anon)
|
|
27
|
+
# Usage: REPL loads defaults + client overrides; validates publicId uniqueness.
|
|
28
|
+
# Example: For confidential client, generate UUID publicIds; pii=true → policy.mfa.required=true.
|