NodeLock is an internal-grade network node allocation platform designed to eliminate reservation chaos for shared IP-addressable infrastructure (for example OLTs, lab nodes, and troubleshooting chassis).
- Reduced reservation coordination overhead (mail + chat ping-pong) by approximately 90% in the team where it is currently adopted.
- Introduced time-bound, auditable allocation records with clear ownership and return accountability.
- Enforced one-active-reservation-per-vault semantics to prevent double booking and operational ambiguity.
In network labs and integration teams, expensive and scarce network nodes are usually shared across multiple engineers and sub-teams. Without a centralized reservation ledger, teams experience recurring operational issues:
- Manual coordination overhead across chat/mail.
- Lost accountability for who owns a setup at a given time.
- Scheduling conflicts and accidental overlap.
- Missing audit trail for post-incident and root-cause workflows.
NodeLock addresses this by introducing a structured reservation lifecycle with owner assignment, borrow windows, controlled return, and archival history.
NodeLock is a Flask-based web application that manages the lifecycle of network node usage:
- Node inventory registration.
- Ownership assignment (lend window).
- Borrowing/reservation within allowed windows.
- Return flow with authentication and archival.
- Defaulter reporting and notification trigger.
The platform is built with a controller-centric application layer and SQL-backed persistence. The design intentionally favors explicit business transitions over hidden automation, which makes behavior understandable and operable for production support teams.
- Standard Reservation: all network IP nodes must be reserved using a valid Employee ID.
- Timely Release: users must release setups at the end of their reservation window.
- Conflict Resolution: if a required node is occupied, coordinate handoff with the active user before reallocation.
- Accountability: the primary owner remains accountable for setup integrity during the ownership window.
- Deterministic state transitions for reserve and return.
- Validation-first form handling before mutation.
- Atomic DB commit boundaries around critical transitions.
- Recoverable failure handling via flash messaging + logging.
NodeLock is organized around four high-value controller modules that map directly to business capabilities.
Responsibility:
- Establish privileged session (
ADMIN) via key-based authentication. - Gate administrative operations such as inventory creation/edit flows.
Core behavior:
- Uses bcrypt hash verification (
ADMIN_BCRYPT_HASH) from environment. - Creates session principal only on successful credential verification.
Why it matters:
- Keeps privileged write operations behind explicit auth, while preserving lightweight UX for internal tooling.
Responsibility:
- Manage canonical node inventory (ID, IP, title, location, identifier, content).
- Provide create, list, update operations for network assets.
Core behavior:
- Input completeness validation + IP format validation.
- Session-aware admin checks for mutating paths.
- Distinct setup counting for inventory-level observability.
Why it matters:
- Defines the source-of-truth inventory set from which vault ownership slots are instantiated.
Responsibility:
- Manage ownership, reservation, return, deletion, and defaulter reporting.
- Enforce business invariants around time windows and reservation exclusivity.
Core behavior:
- Ownership (
lend) and reservation (borrow) are validated against date windows. - Reservation flow includes anti-conflict checks:
- server-side current state check (already reserved guard),
- hidden vault id consistency check against route id.
- Return flow archives transaction and resets mutable reservation fields.
- Notification pipeline renders defaulter templates and sends report mail.
Why it matters:
- This controller implements the atomic operational lifecycle of shared-node usage.
Responsibility:
- Provide read-only access to historical reservation/return outcomes.
Core behavior:
- Loads archived records for operational audit and historical accountability.
Why it matters:
- Converts transient reservation events into a durable audit trail.
- Admin/user identifies a node from inventory.
- Ownership is created in vault with owner identity and lend window.
- Borrow request is submitted within ownership boundaries.
- Validation checks:
- required fields,
- employee identity presence,
- date-window admissibility,
- anti-tamper vault id check,
- already-reserved guard.
- On return, system archives transaction and restores vault availability.
- Defaulter view and optional report mail support operational follow-up.
- Session-based admin access control.
- Environment-backed bcrypt authentication hash.
- Employee ID-centric identity referencing in reservation paths.
- Historical archive records for post-incident diagnosis.
- Flash + structured logging instrumentation across flow branches.
A major design decision is splitting inventory entities (Node) from temporal allocation entities (NodeVault).
- Node List stores static asset metadata.
- Vault stores dynamic ownership/borrow state with time windows.
Why this is novel and practical:
- One node can participate in one or more ownership contexts over time without duplicating static metadata in inventory workflows.
- It reduces data redundancy and keeps mutable reservation context isolated from immutable node identity.
- It simplifies incident analysis by making "what the node is" independent from "who used it and when".
- Employee ID is used as a memorable operational key for reservation ownership and borrowing.
- This reduces friction in fast-paced lab operations compared to opaque identity tokens.
Reservation and return state transitions are committed as explicit DB transactions.
- On success: commit establishes canonical state.
- On failure: rollback prevents partial update artifacts.
The result is predictable behavior under operational and validation failures.
A vault record can only be actively reserved once at a time.
- Request-time state re-check prevents stale-form assumptions.
- Hidden route/form id coherence check reduces tamper/confusion risk.
This implementation aligns with a pragmatic MVP interpretation:
- Model: SQLAlchemy-backed entity classes (
Node,NodeVault,Archive) + data session lifecycle. - View: Jinja templates for create/lend/borrow/return/archive/report pages.
- Presenter (Controller Layer): Flask controller modules orchestrating validation, business rules, persistence, and response rendering.
flowchart TD
U[User/Admin] --> V[Views\nJinja Templates]
V --> C[Controllers\nAdmin/Node/Vault/Archive]
C --> M[Models\nNode/NodeVault/Archive]
M --> D[(SQLite DB\ninstance/nodelock.db)]
C --> J[(data/auth.json)]
C --> L[(logs/*.log)]
C --> E[SMTP Mail Engine]
Blueprint registration maps URL namespaces to controller handlers:
- Node routes: create/show/edit inventory entries.
- Vault routes: lend/borrow/return/delete/report operations.
- Admin routes: authenticate and session promotion.
- Archive routes: read-only historical listing.
Node:
- Canonical inventory metadata (id, ip, title, location, identifier, content).
NodeVault:
- Ownership and reservation lifecycle state.
- Owner and borrower identity fields.
- lend/borrow window boundaries and availability state.
Archive:
- Immutable historical record of completed usage.
- Validate node + owner + date inputs.
- Resolve owner metadata from auth dataset.
- Persist
NodeVaultrow withAvailablestate.
- Re-fetch current vault state.
- Reject if already reserved.
- Validate requested borrow window within lend window.
- Validate identity and request integrity.
- Persist borrower fields and mark reserved.
- Authenticate return request.
- Persist archival snapshot.
- Reset mutable borrower fields.
- Restore vault availability.
- Query overdue borrow windows.
- Render report template.
- Trigger SMTP notification path.
The Vault controller now contains structured logging at:
- function entry points,
- validation outcomes,
- branch decisions (reserve refusal, id mismatch, auth failure),
- transaction success/failure,
- mail trigger status.
This improves debuggability and operational visibility without changing business behavior.
- Language: Python 3.x
- Web Framework: Flask
- ORM / Persistence: SQLAlchemy + Flask-SQLAlchemy
- Migrations: Flask-Migrate / Alembic
- Templates: Jinja2
- Database: SQLite (
instance/nodelock.db) - Session backend: filesystem-based Flask session
- Auth verification: bcrypt (admin), MD5 (temporary path in vault return auth)
- Notification: SMTP (email MIME pipeline)
- Process control: Bash launcher with PID management
- Python 3.x
- pip
- virtualenv (recommended)
git clone <your-repo-url>
cd equipment_dashboard
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txtCreate required runtime folders if missing:
mkdir -p logs instance flask_sessionConfigure .env (example):
ADMIN_BCRYPT_HASH=<bcrypt-hash>Generate a bcrypt hash:
python3 -c "import bcrypt; print(bcrypt.hashpw(b'YOUR_ADMIN_KEY', bcrypt.gensalt()).decode())"Create local application config from the sanitized template:
cp mock-config.py config.pyThen update local values in config.py if needed for your environment.
Important:
config.pyis intentionally ignored by git.- Keep secrets in local env variables or local config only.
Initialize schema:
python db_init.pyThis creates the SQLite schema under instance/nodelock.db through model metadata registration.
Use .gitignore to avoid committing local runtime artifacts and secrets:
.envvenv/instance/*.dblogs/*.logflask_session/__pycache__/
launch-application.sh supports process control with PID tracking:
./launch-application.sh start dev
./launch-application.sh start test
./launch-application.sh status
./launch-application.sh stopBehavior:
- Starts Flask in background.
- Stores PID in
nodelock.pid. - Writes runtime log stream to
logs/nodelock.log. - Supports graceful stop via SIGTERM.
- User submits admin key.
- Controller validates against
ADMIN_BCRYPT_HASH. - On success,
session["user"] = "ADMIN".
Operational guarantee:
- Administrative write paths are protected by session role checks.
- Admin creates/edits inventory entries.
- Controller validates field completeness + IP format.
- Data persists to
Nodetable.
Operational guarantee:
- Inventory remains normalized and independently manageable.
Ownership path:
- Select node.
- Create ownership slot with lend window.
Borrow path:
- User submits borrow request.
- System revalidates current vault state from DB.
- Rejects already-reserved or invalid id mismatch.
- Enforces date window constraints.
- Marks vault reserved and stores borrower metadata.
Return path:
- Authenticate employee return.
- Archive full transaction.
- Reset vault to available.
Operational guarantee:
- One reservation at a time per vault record.
- Controlled lifecycle with reversibility and auditability.
- Read archived rows.
- Render historical allocation timeline for governance and diagnostics.
This tool originated to solve OLT reservation and sharing challenges in a Nokia context. The published version is a generalized rebuild of the same architecture and operational principles for broader network resource allocation use cases.
I chose MD5 for the MVP identity matching to keep the return-flow lightweight, but the Admin-level authentication uses Bcrypt for industry-standard salted hashing.
- Replace temporary MD5 path in vault return authentication with stronger scheme.
- Move SMTP host/recipients fully to environment configuration.
- Add integration tests for lend/borrow/return edge cases.
- Add optimistic locking/version checks for high-concurrency reservation race windows.
- Introduce role tiers beyond single ADMIN principal.






