Chapter 30Lesson 02300–420 min

Production Capstone: Design, Secure, Automate, Migrate, and Recover an Enterprise Artifact Platform: Implementation and Automation Build-Out

The capstone architecture becomes useful only when another operator can reproduce and verify it. This lesson builds a Community-compatible desired-state workflow around disposable repository definitions, service identities, client endpoints, synthetic artifacts, CI-like publication, exact-byte promotion, evidence capture, and idempotent reconciliation.

ImplementationREST automationIdempotenceCI publicationEvidence pack

Learning objectives

  • Express repository and security configuration as desired state separate from credentials.
  • Reconcile disposable resources idempotently: inspect, diff, create/update, verify, and rerun safely.
  • Publish synthetic artifacts with a CI-like service identity and preserve immutable identity evidence.
  • Promote exact bytes without rebuilding and prove byte equality.
  • Produce operator evidence and rollback/cleanup instructions for every capstone resource.
Dated capstone baseline (27 August 2026). The lessons use Nexus Repository 3.95.2-01 and Java 21 as the reference line. The live release notes, feature matrix, format support, migration/upgrade gates, and edition/licensing requirements must be re-checked before any production implementation.
Two targets, one operating model. The production architecture may include external PostgreSQL, Pro HA, licensed Firewall/IQ, enterprise identity, and shared/object storage. The mandatory lab remains Community/free-compatible and disposable, using synthetic namespaces and fixtures where a paid or infrastructure-heavy capability would otherwise be required.
Safety boundary. Never run this capstone against an employer/production Nexus instance, production database/blob store, real SSO, CI secrets, public DNS, valuable package namespace, or recovery backup. Destructive operations are limited to resources explicitly named capstone-lab-*, and every change has preflight, evidence, verification, and rollback.

1. Preflight before mutation

Record the running Nexus version/edition/runtime, database type, blob store used by the lab repositories, base URL, current repository names, and whether the API schema matches the examples. The current instance's OpenAPI document is authoritative for exact request fields. Never paste a production admin password into a script to “get started.”

CAPSTONE BASELINE
Nexus: 3.95.2-01 reference line
Java: 21
Edition: Community mandatory path
Base URL: http://127.0.0.1:8081
Namespace prefix: capstone-lab-
Package namespaces: com.example / @learner-example
Credentials: disposable lab identities injected at runtime

2. Desired state is data, secrets are not

{
  "repositories": [
    {"name":"capstone-lab-maven-releases","format":"maven2","type":"hosted"},
    {"name":"capstone-lab-maven-central","format":"maven2","type":"proxy"},
    {"name":"capstone-lab-maven-public","format":"maven2","type":"group",
     "members":["capstone-lab-maven-releases","capstone-lab-maven-central"]},
    {"name":"capstone-lab-npm-internal","format":"npm","type":"hosted"},
    {"name":"capstone-lab-npmjs","format":"npm","type":"proxy"},
    {"name":"capstone-lab-npm-public","format":"npm","type":"group",
     "members":["capstone-lab-npm-internal","capstone-lab-npmjs"]},
    {"name":"capstone-lab-release-evidence","format":"raw","type":"hosted"}
  ],
  "serviceIdentities": ["capstone-publisher","capstone-reader","capstone-reconciler"]
}

The desired-state file contains names and intent, not passwords/tokens. Runtime secrets come from an environment/CI secret store and are redacted from logs.

3. Reconciliation loop

Idempotent configuration flow
flowchart TD
  D[Desired state] --> G[GET actual state]
  G --> N[Normalize relevant fields]
  N --> C{Equal?}
  C -->|yes| NOOP[No operation]
  C -->|no, missing| CREATE[Create]
  C -->|no, exists| UPDATE[Update carefully]
  CREATE --> VERIFY[Read back + verify]
  UPDATE --> VERIFY
  VERIFY --> EVIDENCE[Write redacted evidence]

Delete-and-recreate is not the default update strategy because repositories can contain valuable content and identity relationships. In the mandatory lab, deletion is permitted only for empty/disposable capstone-lab-* resources during cleanup.

4. Fixture reconciler: prove idempotence before touching Nexus

desired = {
  "capstone-lab-maven-releases": {"format":"maven2","type":"hosted"},
  "capstone-lab-maven-public": {"format":"maven2","type":"group"},
  "capstone-lab-npm-internal": {"format":"npm","type":"hosted"},
  "capstone-lab-npm-public": {"format":"npm","type":"group"},
  "capstone-lab-release-evidence": {"format":"raw","type":"hosted"},
}
actual = {}

def reconcile(actual, desired):
    actions=[]
    for name,spec in desired.items():
        if name not in actual:
            actual[name]=spec.copy(); actions.append(("create",name))
        elif actual[name] != spec:
            actual[name]=spec.copy(); actions.append(("update",name))
        else:
            actions.append(("noop",name))
    return actions

first = reconcile(actual, desired)
second = reconcile(actual, desired)
print(first)
print(second)
assert all(a == "create" for a,_ in first)
assert all(a == "noop" for a,_ in second)

When converted to REST automation, preserve the same logic and handle HTTP 400/401/403/404/409 deliberately. Query the instance-specific Swagger/OpenAPI document before assuming a request schema.

5. Least-privilege implementation order

  1. Create/verify blob store only if the lab requires a dedicated one.
  2. Create hosted repositories first.
  3. Create proxies only when their remote upstream and routing behavior are explicitly defined.
  4. Create groups after members exist and verify member order.
  5. Create narrowly scoped roles/privileges.
  6. Create disposable service users mapped only to required roles.
  7. Configure temporary clients to use Nexus endpoints.
  8. Run negative authorization tests before publication.

6. Read-only API preflight

# Safe lab read. Do not expose credentials in command history/logs.
NEXUS_URL='http://127.0.0.1:8081'
curl --fail --silent "$NEXUS_URL/service/rest/v1/status"

# Inspect repository inventory with a disposable authenticated identity.
curl --fail --silent --user "$NEXUS_USER:$NEXUS_PASSWORD" \
  "$NEXUS_URL/service/rest/v1/repositories"

# Inspect the exact running API schema before writes.
curl --fail --silent --user "$NEXUS_USER:$NEXUS_PASSWORD" \
  "$NEXUS_URL/service/rest/swagger.json" -o capstone-swagger.json

Use environment variables or a secret mechanism appropriate to the shell/CI runner and ensure command tracing is disabled. The fake examples are not production credential-management instructions.

7. Synthetic multi-format publication

Create three harmless release objects from the same fictional build:

Format/evidence Identity Target
Maven com.example:capstone-lib:1.0.0 capstone-lab-maven-releases
npm @learner-example/capstone-lib@1.0.0 capstone-lab-npm-internal
Raw evidence build-20260827/manifest.json capstone-lab-release-evidence

The package-manager commands remain temporary-client configuration. Do not modify the learner's global Maven/npm settings without rollback.

8. Build once and record identity

from hashlib import sha256
build_id = "build-20260827-001"
artifacts = {
  "capstone-lib-1.0.0.jar": b"synthetic-java-release\n",
  "learner-example-capstone-lib-1.0.0.tgz": b"synthetic-npm-release\n",
  "manifest.json": b'{"build":"build-20260827-001"}\n',
}
manifest={}
for name,data in artifacts.items():
    manifest[name]={"buildId":build_id,"sha256":sha256(data).hexdigest(),"bytes":len(data)}
print(manifest)
assert len({v["buildId"] for v in manifest.values()}) == 1

Coordinates, build ID, SHA-256, publication time, and source commit are separate evidence. A checksum proves byte equality, not trusted origin or vulnerability safety.

9. Community-compatible promotion proof

Native Staging is Pro-only. The mandatory capstone uses a fixture that copies the exact already-built bytes into a release-stage directory and compares hashes:

from hashlib import sha256
candidate=b"capstone-release-1.0.0\n"
release=bytes(candidate)  # transfer exact bytes; no rebuild
assert sha256(candidate).digest() == sha256(release).digest()
print("promotion-byte-identity: PASS")

If you have a licensed environment, Staging can be an optional extension, but the acceptance criterion remains exact artifact identity plus governance evidence.

10. Webhook/event automation boundary

A repository event can wake downstream automation, but receivers must treat delivery as untrusted input until authenticity is validated and duplicate deliveries are handled idempotently. Never let “event received” mean “release approved.” The approval decision depends on immutable identity plus test/policy evidence.

11. Operator evidence packet

capstone-evidence/
  00-baseline.md
  01-desired-state.json
  02-actual-state-redacted.json
  03-authz-matrix.csv
  04-publication-manifest.json
  05-promotion-proof.json
  06-cleanup-preview.md
  07-observability-baseline.json
  08-backup-restore-proof.md
  09-upgrade-migration-gates.md
  10-runbooks/

No credentials, Authorization headers, private keys, real production URLs, or unreviewed support ZIPs belong in the evidence packet.

12. Rerun and drift challenge

After the second no-op reconciliation, manually alter the fixture so capstone-lab-maven-public no longer includes the hosted member. The reconciler should report one drift and restore only that membership. It must not recreate unrelated repositories or delete content.

13. Cleanup

Before cleanup, list resources and prove every target starts with capstone-lab-. Delete only empty/disposable capstone resources through supported Nexus mechanisms and remove temporary client config. Never delete blob files/database rows directly. Keep the redacted evidence packet if you want to use it in Lessons 3–5.

Knowledge check

What proves reconciliation is idempotent?

Why must repository credentials be absent from desired-state files?

What is the correct publication target for internal Maven releases?

What proves Community-path promotion preserved identity?

Why is a webhook event insufficient to approve a release?

Summary and next step

The target architecture is now reproducible as desired state, with idempotent reconciliation, scoped identities, controlled clients, synthetic multi-format publication, build-once identity, exact-byte promotion proof, and an operator evidence packet.

Lesson 3 validates whether this implementation is actually secure, governable, recoverable, and supportable under production constraints rather than merely functional.

Official references and version notes

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.