Skip to main content

Salesforce metadata namespace auditing and fail-closed refactoring

Project description

NamespaceForge CLI

NamespaceForge audits and safely refactors namespace references in Salesforce metadata source. Version 0.2 inventories Apex, LWC, Aura, and XML metadata, resolves package-owned symbols, previews add/remove/replace operations, and can execute an approved plan with integrity checks, recoverable backups, and rollback support.

Installation

Python 3.11 or newer is required.

cd namespaceforge-cli
python -m venv .venv

Windows:

.venv\Scripts\activate
pip install -e ".[dev]"

Linux/macOS:

source .venv/bin/activate
pip install -e ".[dev]"

Audit and planning

namespaceforge --help
namespaceforge --version
namespaceforge scan ../force-app/main/default
namespaceforge scan ../force-app/main/default --format json
namespaceforge audit ../force-app/main/default --namespace zPFX
namespaceforge audit ../force-app/main/default --format json --output report.json
namespaceforge audit ../force-app/main/default --fail-on-issues
namespaceforge plan replace ../force-app/main/default --from oldPFX --to zPFX
namespaceforge plan add ../force-app/main/default --namespace zPFX
namespaceforge plan remove ../force-app/main/default --namespace zPFX

All plan commands are strictly read-only. Review their safe, review, and protected classifications before authorizing a transformation.

Applying transformations

Run the corresponding plan first, commit or otherwise preserve the current source state, then use an explicit apply command:

namespaceforge apply replace ../force-app/main/default --from oldPFX --to zPFX --yes
namespaceforge apply add ../force-app/main/default --namespace zPFX --yes
namespaceforge apply remove ../force-app/main/default --namespace zPFX --yes

Use --backup-dir PATH to select a persistent backup root outside the scanned tree. Without it, NamespaceForge uses .namespaceforge/backups at the Salesforce project or Git repository root when one can be discovered. Each successful run prints its unique manifest and backup paths.

Machine-readable transformation output is available without mixing diagnostics into JSON stdout:

namespaceforge apply replace ../force-app/main/default \
  --from oldPFX --to zPFX --yes --format json --output transform-report.json

Fail-closed safety model

NamespaceForge applies a transformation only when all of these conditions hold:

  • --yes explicitly authorizes source modification.
  • The scan completed without unreadable files or scanner errors.
  • The plan contains no review occurrences; protected declarations and comments remain untouched.
  • Every target remains inside the resolved scan root and matches the content hash captured during planning.
  • Backups and a prepared manifest are written outside the scanned tree before the first source write.
  • Source bytes are checked again immediately before each atomic file replacement.

If a later write fails, already modified files are restored from the in-memory originals and the manifest records the rollback state. UTF-8 BOMs, CRLF/LF line endings, and file modes are preserved.

Rollback

Restore a completed transformation using its manifest:

namespaceforge rollback .namespaceforge/backups/<run-id>/manifest.json --yes

Rollback verifies both the backup hash and each current source hash before writing anything. If a file was edited after the transformation, the entire rollback aborts without overwriting that work. Rollback is idempotent.

Configuration

Create namespaceforge.toml in the working directory, or pass --config PATH:

[namespaceforge]
namespace = "zPFX"
source_path = "force-app/main/default"
exclude = ["**/.git/**", "**/node_modules/**"]

[audit]
fail_on_issues = false
minimum_confidence = 0.6

Without a path, commands use force-app/main/default or the configured source_path. CLI arguments override configuration values.

Reports and schemas

Text reports are optimized for people. JSON reports use stable schema version 1.0. Standalone Draft 2020-12 contracts are packaged for:

  • scan reports
  • audit reports
  • read-only plan reports
  • transformation results
  • durable transformation manifests

The schemas remain accessible from namespaceforge/schemas through importlib.resources after wheel installation.

For source safety, any explicit --output report must resolve outside the scanned directory. NamespaceForge returns exit code 2 before transforming when an apply report targets the source tree.

Exit codes

Code Meaning
0 Successful command
1 Warnings or errors found with audit --fail-on-issues
2 Invalid CLI usage, configuration, confirmation, or output path
3 Scan path missing or inaccessible
4 Unexpected internal failure
5 Transformation or rollback safely aborted

Development and release validation

pytest
pytest --cov=namespaceforge
python -m build
python -m pip install dist/namespaceforge-0.2.0-py3-none-any.whl
namespaceforge --version

Tests use isolated metadata trees and require no Salesforce org. CI runs on Windows and Linux with Python 3.11, 3.12, and 3.13.

Demo

The tracked demo is outside force-app, so it cannot affect the managed package. Plan commands can run directly against it. To test an apply command, first copy the demo to an untracked temporary directory and transform only that copy.

.\namespaceforge-cli\.venv\Scripts\namespaceforge.exe scan .\namespaceforge-cli\examples\demo-metadata
.\namespaceforge-cli\.venv\Scripts\namespaceforge.exe audit .\namespaceforge-cli\examples\demo-metadata --namespace zPFX
.\namespaceforge-cli\.venv\Scripts\namespaceforge.exe plan replace .\namespaceforge-cli\examples\demo-metadata --from oldPFX --to zPFX

Current limitations

  • Reference discovery remains token based; XML ownership extraction uses structured parsing with a recovery fallback.
  • Apply commands intentionally refuse every review-required plan. There is no override for partial or ambiguous transformations.
  • Unnamespaced custom tokens become high-confidence findings only when ownership can be established from declarations in the scanned tree.
  • Third-party namespaces remain non-blocking unless the referenced symbol is owned by the scanned package.
  • Dynamic Apex, generated JavaScript, encoded references, and uncommon metadata forms can require manual review or remain undiscovered.
  • Source <fullName> declarations for objects, fields, and labels are protected and remain unmodified.
  • Correct expected-namespace references are reported as informational findings.
  • Always inspect the plan and use version control before applying a transformation.

Roadmap

The next milestone is parser-backed Apex and JavaScript symbol resolution, followed by Salesforce API/OAuth integration and a VS Code workflow. Those capabilities provide the foundation for an AppExchange API or hybrid solution.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

namespaceforge-0.2.0.tar.gz (39.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

namespaceforge-0.2.0-py3-none-any.whl (37.3 kB view details)

Uploaded Python 3

File details

Details for the file namespaceforge-0.2.0.tar.gz.

File metadata

  • Download URL: namespaceforge-0.2.0.tar.gz
  • Upload date:
  • Size: 39.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for namespaceforge-0.2.0.tar.gz
Algorithm Hash digest
SHA256 80c39370b3458a1ae197d95d7fecdb21d4b6d5648df93c5d40b2426ec21fd9e3
MD5 abe616cfcabdbe5cd3dc06b75ce8c97a
BLAKE2b-256 d5b59e6a6ba365f7ee03d34a77e347a8e1d94d55ac04758ca513d9fb6c537acd

See more details on using hashes here.

Provenance

The following attestation bundles were made for namespaceforge-0.2.0.tar.gz:

Publisher: publish-pypi.yml on AbdelGahffarZakaria/NamespaceForge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file namespaceforge-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: namespaceforge-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 37.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for namespaceforge-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5ca39ece10f2dec937a5502d64f3c60cb7dfc4dae620521008894ece9d3dae37
MD5 6639373819e5375ad47895ca43716163
BLAKE2b-256 ec985c273e361bdfaa01eda119577e96d40b0eb731b393940c63e7a86fa0a329

See more details on using hashes here.

Provenance

The following attestation bundles were made for namespaceforge-0.2.0-py3-none-any.whl:

Publisher: publish-pypi.yml on AbdelGahffarZakaria/NamespaceForge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page