Skip to content

SmartInventory 3.0 — Legacy Architecture & Feature Study

Purpose: Ground-truth map of the existing Lepton SmartInventory / NetworkAccess product, produced to inform the greenfield Lepton Infrastructure Cloud rewrite (see Lepton_Infrastructure_Cloud_PRD.md, Lepton_AI_Native_Operations_Vision.md, NetworkAccess_Product_Profile_and_BRD.md).

Subject: references/SmartInventory-3.0/ @ branch develop (the product mainline), private repo github.com/LeptonSoftware/SmartInventory-3.0.

Method: Five parallel read-only code-exploration passes over the develop checkout (web app; BusinessLogics/DataAccess; Models + EF context + MapFiles; the other ~20 projects; git ref-diffs for per-customer divergence). Findings below are evidenced from source; counts are approximate.

Date: 2026-06-16


0. Read this first — caveats on what the code can and cannot tell us

  1. The real domain logic lives in PostgreSQL, not in this repo. ~536 CREATE FUNCTION stored procedures are the business logic; the C# BL*/DA* layers mostly marshal parameters. Proc bodies are NOT in the repo (they’re deployed via a custom “Deployment Manager” tool). The C# alone is insufficient to plan a rewrite — the live DB’s fn_* library must be exported and reverse-engineered separately.
  2. MigrationScripts/ is partial and unreliable (per the repo’s own AGENTS.md). The DDL for the most important tables — the central geometry tables point_master/line_master/polygon_master and the metadata registry layer_details — is not present; their columns are inferred from usage. The live database is the source of truth for schema.
  3. Customer-specific code is NOT in this checkout. develop is the generic mainline; per-customer logic lives in develop-<customer> branches (§9). Conclusions about “what the product does” describe the generic product.
  4. There are no automated tests anywhere in the repo.

1. TL;DR — the ten findings that shape the rewrite

  1. Stack is end-of-life. ASP.NET MVC 5 on .NET Framework 4.8, EF6 + Npgsql, server-rendered Razor + jQuery, no DI, no tests. ~23 projects in one Visual Studio solution.
  2. Everything-is-a-layer metadata engine. A layer_details table (one row per entity type, ~110 boolean feature flags) + per-entity item_template_* (specs) + a dynamic_controls/entity_additional_attributes EAV overlay is the real “Equipment Model Builder.” Powerful, but it spawns ~5 parallel tables per entity type (att_details_*, item_template_*, temp_du_*, audit_att_details_*, vw_*_map).
  3. Geometry is decoupled from attributes. Attributes sit in wide att_details_<entity> tables; geometry sits centrally in point_master/line_master/polygon_master (sp_geometry, SRID 4326), joined by system_id. C# never touches typed geometry — it ships WKT/“lon lat” strings ([NotMapped] string geom); PostGIS does all spatial work server-side (5,137 ST_* calls).
  4. Topology is implicit but everywhere. Connectivity is encoded in FK-style columns (a_system_id/b_system_id, parent_system_id) and splice/port tables, resolved by PG functions. This is a natural fit for the PRD’s explicit graph model.
  5. Business logic is proc-driven. ~1,200 ExecuteProcedure call sites across 163 files; a stringly-typed reflection contract (anonymous-object property names must match proc parameter names) with no compile-time safety.
  6. God objects dominate. DAMisc.cs (4,862 LOC, instantiated 67×), DLWFMTicket.cs (3,945), DALayer.cs (2,036), DAUser.cs (1,846); LibraryController.cs (13,752), ReportController.cs (12,860), Main.js (~34k LOC). Decomposing these is the first rewrite task.
  7. All four marketed modules are present — SmartInventory (core), SmartPlanner (in-repo, SmartPlannerController + SmartPlanner.js 4,598 LOC), SmartOps = “WFM” (Workforce controllers + FEController + WFMNotificationService), SmartSQ = the SmartFeasibility app (a separate deployable in the same solution, reached by redirect, module code SFS). Note: the marketing names “SmartSQ”/“SmartOps” do not appear in code.
  8. Per-customer divergence is real feature forking, not branding. ~1,626 branches; customer forks add whole controllers (MobileFormController +9,186 on ACT), per-tenant .sql schema, and custom dynamic-form stacks. Baselines rot (Safaricom is 1,656 commits behind develop). This is the strongest signal that config-not-code multi-tenancy is the #1 rewrite requirement.
  9. Secrets are committed in plaintext across every project’s Web.config/App.config and in MapFiles/datashare.inc (DB passwords, Google Maps keys, SSO client secrets, FTP creds). Must be externalized/rotated.
  10. Integration surface is large and customer-specific. Multiple SSO/IdP stacks (ADFS, Azure AD, LDAP, Jio ADOID/Seco, Airtel-OID SOAP), multiple SMS gateways (RIL4G, Synermaxx, Twilio), per-customer SMTP, OSS/BSS + ERP (Converge SOAP), FTP, an external routing engine. Integrations are bolted in per deployment.

2. Solution & project topology

One VS2022 solution: Source/SmartInventory/SmartInventory.sln. ~23 projects.

Core application layers

ProjectTypeRole
SmartInventoryASP.NET MVC 5 web appThe main product UI (40 root + 29 Admin controllers, 697 views)
SmartInventoryServicesWeb API (OWIN)REST backend for the mobile app + web app; OAuth /token
IntegrationServicesWeb API (OWIN, Swagger)Third-party OSS/BSS integration API; OAuth /GenerateToken
SmartFeasibilityMVC 5 web appStandalone service-qualification tool (= “SmartSQ”, module SFS)
BusinessLogicsClass libBL* business layer (209 files, ~198 classes)
DataAccessClass libDA*/DL* data layer (215 files), EF6/Npgsql, repo + procs
ModelsClass libShared DTOs (216 files, ~1,624 type decls)
UtilityClass libLogging, data plumbing, SignalR hub, HTTP clients, SSO (ADOID/Seco, Airtel/Jio SOAP)

Supporting libraries

ProjectRole
DataUploaderBulk import (~46 entity types): Excel/KML/Shape/TAB/DXF/GeoJSON → temp_* staging → main tables
GIS_ConvertorSpatial format conversion (SharpKml in-process; shells out to bundled ogr2ogr.exe/GDAL)
GoogleMapServicesTyped Google Maps REST client (Geocode/Directions/DistanceMatrix/Places)
CommunicationLibraryNewer SMS/WhatsApp abstraction — only Twilio SMS implemented; WhatsApp is a stub; not yet wired in
Resourcesi18n engine (DB-backed res_resources or XML; codegens typed Resources class)
CodeINLicense/expiry enforcement (decodes AES-encrypted license from global_settings)
ApplicationConfigCompile-time constants (incl. base64 admin passwords — smell)

Standalone executables / services

ProjectTypeRole
WFMNotificationServiceWindows ServiceWorkforce notifications — 8 timers, email+SMS for job-order lifecycle + daily report emails
ServiceabilityWinServiceWindows ServiceFTP folder-watch bulk serviceability (HOBS/Converge); 5s timer
RoutingDataSyncConsoleRebuilds the Postgres routing network (fn_fs_create_routingData) for feasibility/shortest-path
UtilizationEmailSchedulerConsoleTask-Scheduler: utilization proc → Excel → email
BackupDownloadUtilityConsolePulls DB dump from FTP, zips app+mapfiles
RSAImplementationConsole (modern .NET)Offline vendor CLI: generates the license string CodeIN validates
MultilingualJunkKeysMVC 5 web appInternal dev tool: finds unreferenced resource keys

3. Architecture & layering

Strict 3-layer, parallel-named, no DI:

Controller (SmartInventory/Controllers/)
→ BusinessLogics/BL<Entity>.cs (new'd directly by controller)
→ DataAccess/DA<Entity>.cs (new'd directly by BL)
→ GenericRepository.ExecuteProcedure<T>() → PostgreSQL fn_*(...)
  • No container, no interfaces, no unit-of-work. Controllers new BL; BL news DA. DataAccess/DBHelpers/Repository.cs constructs a fresh GenericRepository<MainContext> (new DbContext) on every property access → no transaction can span multiple proc calls. Simultaneously, 58 DA classes carry copy-pasted hand-rolled thread-safe singleton boilerplate that coexists inconsistently with the new path.
  • Data access is overwhelmingly stored-proc. GenericRepository.ExecuteProcedure<T>(proc, anonObj, isProcReturnJson) builds select * from proc(@p…) via ProcHelper reflection. ~1,200 call sites / 163 files. Procs follow fn_<verb>_<area> (594 fn_get_* references; families fn_nwt_*, fn_wfm_*, fn_sf_*, fn_uploader_*, fn_row_*, fn_splicing_*). Many return JSON (row_to_json) deserialized client-side.
  • EF6 is a thin conduit. MainContext maps ~330 entities (Fluent API, one giant OnModelCreating) but exposes only ~40 DbSet<> (mostly WFM/user); real EF LINQ CRUD covers a minority of tables.
  • Escape hatches: raw ExecuteSqlCommand/GetDataTable(sql) and the legacy DataAccess/PostgreSQL.cs raw-Npgsql class (confined to TempUpload/ bulk loaders, 31 files) — an injection/maintenance hazard.
  • Second DB context RoutingContext (repo_routing) for routing/topology — possibly a separate physical DB (unconfirmed).
  • Two MainContext.cs copies exist (Context/ and DBContext/) — duplication.

4. Domain & data model

4.1 Entity catalog (evidenced from BL*/DA* pairs + *Master models)

  • Physical / OSP assets: Cable, Pole, Trench, Manhole, Handhole, Duct, Microduct, Conduit, Vault, Chamber/Structure, GIpipe, Rebar, Reinstatement, ROW (right-of-way), Loop, Slack. (DACable.cs 1,002 LOC; DAROW.cs 703.)
  • Logical / connectivity: FiberLink, OSPSplicing, SpliceTray, PortInfo, FiberCutTracing, PatchCord, FATConnection, Coupler.
  • Inside-plant / equipment (FTTx active+passive): Splitter, SpliceClosure (SC), ONT/ONU, DLC, DP, POD/MPOD, FMS, PatchPanel, Rack, Cabinet, WallMount, JunctionBox, Accessories, Building (premises/MDU). No dedicated OLT or ODF entity found (likely folded under FMS/Rack, or out of scope — unsure).
  • Wireless overlay: Antenna, Microwave, Sector, Tower, InstallationInfo. (Quirk: TowerController persists towers as VaultMaster — entity overloading.)
  • Customer / commercial: Customer (+ Site/Associate/Trench customer), Wireline/Wireless customers, Serviceability/Feasibility, DarkFiberFeasibility, Competitor, MaintenanceCharges, SiteInfo, Lmc (last-mile).
  • Workforce / ops: JobOrder, JobPack, WFM ticket, NetworkTicket, Fault + FaultStatusHistory, SurveyAssignment, ATAcceptance (acceptance testing), UserTimeSheet, Process/Execution.
  • Admin / master-data: User, Roles, Layer/LayerMaster/LayerConfiguration, ItemTemplate/Template, Vendor/VendorSpecification, Project/Area/Region/Province, ISP/ISPModel/ISPPort, KPIMaster, OpticalLinkBudget, DynamicAttributes, BOM, and the *Setting family (Global/Configuration/Advanced/Label/Search/CableColor/TubeColor/DynamicTheme).
  • Reporting / cross-cutting: Dashboard, ExportData/ExportUtility, MapReport/MapPrintManager (PDF/map gen), Search/DeviceSearch, VectorLayers, Redline, SmartPlanner, Geom, logging (Error/WebRequest/API/PrintLog), and the catch-all Misc.

4.2 The storage model (the architectural keystone)

layer_details (metadata registry — 1 row per entity type, ~110 flags)
│ declares → layer_table, layer_template_table, layer_view,
│ report_view_name, audit_table_name, geom_type, map_abbr,
│ is_template_required, is_dynamic_control_enable, is_split_allowed, …
┌──────────────┼───────────────────────────────────────────────┐
▼ ▼ ▼ ▼
att_details_<e> item_template_<e> point/line/polygon_master dynamic_controls
(wide attribute (per-entity spec/ (CENTRAL GEOMETRY: + entity_additional_
columns + template; vendor/ sp_geometry geom, SRID attributes
latitude/long + brand/model/port) 4326, joined by system_id) (EAV custom fields)
system_id)
  • Hybrid attribute model: primary storage is wide, denormalized fixed-column att_details_* tables (e.g. att_details_slack ~60 typed columns); an EAV overlay (dynamic_controls defines per-entity custom fields → values in entity_additional_attributes) provides “add a field without a migration,” gated per layer by is_dynamic_control_enable.
  • Geometry lives apart in point_master/line_master/polygon_master (sp_geometry geometry, SRID 4326; plus sp_centroid/center_line_geom/buffer_geom), keyed by system_id + entity_type. C# models carry geometry only as [NotMapped] string geom (WKT/text); 50 model files do this. PostGIS does all spatial computation.
  • “Equipment Model Builder” mechanics: (1) register an entity = insert a layer_details row + toggle flags; (2) specs via item_template_* / shared item_template_master; (3) in-building equipment via an isp_type → brand → base_model → model → port master hierarchy; (4) custom fields via the dynamic_controls EAV.
  • Per-entity table sprawl: each entity type tends to get att_details_*, item_template_*, temp_du_* (uploader staging), audit_att_details_* (audit shadow), and a vw_*_map render view — the main duplication driver a rewrite can collapse.
  • Naming conventions (confirmed): att_details_*, item_template_*, *_master, global_settings (key/value/type), vw_* views, temp_du_* staging, audit_att_details_*.

5. Feature inventory by module

5.1 SmartInventory (core asset management) — in repo

  • Full FTTx OSP catalog CRUD (131 Views/Library/* partials); cable/duct/trench/microduct split & merge; fiber/tube/core editing.
  • Asset cloning (single + bulk with dependencies); barcode/QR; geotagged images + multi-file/ZIP attachments.
  • ROW apply/approve/reject workflow; bulk as-built/dormant/decommissioned conversion over a radius; loop/slack mgmt; faults; maintenance charges.
  • In-building / MDU design (ISPController, 6,061 LOC): building→floor→shaft→room→rack→equipment with X/Y/Z placement; in-building cabling/splitters/ONT/CPE; visual room/rack view (d3 SVG).
  • Splicing (SplicingController, 2,873 LOC): drag-drop splice GUI (jsPlumb); cable/ODF/CPE connections; tray/closure port mgmt; port status & history; connection path finder; CPF→KML; optical link budget per wavelength with splitter-loss tables. (OTDR = metadata fields only — otdr_distance/otdr_length; no .sor trace import.)
  • Fiber links / circuits (FiberLinkController): end-to-end circuit inventory, customer association, GIS-vs-cable length.
  • Reports & export (ReportController, 12,860 LOC): Excel (NPOI), PDF, KML, DXF (CAD), Shapefile, CSV; SLD (Single Line Diagram) and Butterfly diagrams; end-to-end schematic (d3 tree); BOM/BOQ + construction BOM with overhead-formula engine; ROW/LMC/VSAT/utilization reports; async export to FTP; barcode reports.
  • Audit trail of entity changes with multilingual labels + export.

5.2 SmartPlanner (network planning) — in repo

SmartPlannerController (3,786 LOC) + SmartPlanner.js (4,598 LOC): demand points, ring topology design, route optimization (Google Directions + proprietary “LeptonRouteAPI”), bulk auto-plan, restricted-area avoidance, trench-length-by-landbase, plan clone/version, plan→BOM/BOQ. Pulled into inventory via IntegrationController.

5.3 SmartOps = “WFM” (field workforce) — in repo

WorkforceController (3,256 LOC) + FEController (wfm/mobile/v1.0 in SmartInventoryServices) + BusinessLogics/WFM + DataAccess/WFM + WFMNotificationService: job-order assignment, ticket open/close (sources ONT_HOBS/OUTAGE/Trouble-Ticket), 3-tier route-issue approval, timesheets/roster, field survey (SurveyAreaController), WFM SLA/utilization charts, HPSM (HP Service Manager) + NMS ticket integration. (“SmartOps” appears nowhere in code; SI.MobileOps is only an APK-distribution service.)

5.4 SmartSQ = SmartFeasibility app — separate deployable in the repo

Standalone MVC app (module SFS), reached from the main app via redirect to SmartFeasibilityURL. Single + bulk (Excel) address feasibility, FTTH ONT reachability, route/core availability, KML/PDF/Excel/BOM export, external routing engine. The runtime serviceability check for OSS callers is a distinct path (IntegrationServices/ServiceController, ServiceabilityWinService, BLServiceability).

5.5 Admin / platform

Users/roles/permissions per layer; OTP/2FA config; vendor/equipment/accessory/spec masters; layer/ortho/business-layer GIS config; DynamicForm low-code custom fields; DynamicTheme runtime white-labeling; multilingual resource mgmt; OAuth API-consumer mgmt; DB backup & long-query killer. 45 fine-grained module codes (RDL, FLK, NWT, BMQ, ROW, LMC, VSAT, WFM, SFS, …) gate UI features — a per-feature licensing scheme distinct from the 4 marketed modules.


6. GIS / mapping stack

  • Dual rendering: Google Maps (or OpenStreetMap) for basemap tiles + self-hosted MapServer for the entity overlay. Selected via MapAuthType=KEY|CLIENT, mapServerURL, mapDirPath. deck.gl (8.9 & 9.0) + turf.js add WebGL overlays; jsts for client-side topology; jsPlumb for splicing; d3 for schematics.
  • 18 .map files (Source/MapFiles/): NetworkEntities* (~58 layers — the FTTx network) and LandBaseEntities* (basemap), with Label/NoLabel/-Scale2/Mobile/_feasibility variants; plus Legend.map, OrthoImage.map (raster), jiolayers.map (Jio competitor data).
  • Rendering wiring (datashare.inc): CONNECTIONTYPE postgis with plaintext DB creds; DATA 'sp_geometry FROM vw_att_details_<entity>_map USING UNIQUE system_id USING srid=4326'; per-user row filtering via user_permission_area; runtime %...Filter% placeholders. Symbology by [network_status] (P/A/D) and entity attrs → status-foldered PNG icons (~270) + symbols.sym (201 symbols). SRID 4326 throughout.

7. Integrations & external systems

  • SSO / IdP: ADFS (Spectra); Azure AD / MS Graph; LDAP (Vodafone); Jio “ADOID/Seco” OAuth + OIAM; Airtel-OID + Jio-AD LDAP-over-SOAP (Utility/ADOIDSecoAuth.cs); plus Forms + master-password bypass. Multiple identity backends are switched inside OAuthProvider.GrantResourceOwnerCredentials.
  • SMS: RIL4G gateway (OTP), Synermaxx/ComClark (Philippines, via WFMNotificationService), Twilio (lib exists, not wired). WhatsApp = stub.
  • Email/SMTP: per-customer (Converge ICT, Safaricom).
  • OSS/BSS & ERP: IntegrationServices (OSSIntegrationController: entity lookup, alarm status, FAT-port reserve/release, ONT activation, serviceability); Converge ERP SOAP/WCF (CreateInvIssue/CreateInvReturn for CPE inventory). HPSM + NMS ticketing.
  • Routing engine: external routingAPIUrl (JWT), SmartFeasibility/Helper/RouteAPIHelper.cs.
  • Sister product: SmartPlanner via ImportDataAPIRequest.
  • FTP (attachments + backups), SMB share (file storage), PostgreSQL (every project; conn string AES-decrypted when ISEncryptedConnection=true).
  • AuthN to our own APIs: SmartInventoryServices = OAuth ROPC, opaque MachineKey bearer tokens (not JWT), /token; IntegrationServices = OAuth, /GenerateToken, validates (user, pass, source) against APIConsumerMaster, optional client-IP allowlist, CORS *, AllowInsecureHttp=true.

8. Background / async processing

  • WFMNotificationService (Win svc): 8 timers → SMS+email for JO lifecycle (unassigned/acknowledge/delayed/no-task/customer reminder) + 2 daily report emails; reads vw_wfm_*, writes wfm_notification/wfm_email_sms_log.
  • ServiceabilityWinService (Win svc): 5s FTP folder-watch → serviceability/GPON API (OAuth) → NAP-match results to FTP. Tag HOBS/Converge.
  • UtilizationEmailScheduler (console): utilization proc → Excel → email.
  • RoutingDataSync (console): rebuild routing network for feasibility/shortest-path.
  • BackupDownloadUtility (console): FTP DB dump + zip app/mapfiles.
  • DataUploader (library, synchronous from web app): Excel/KML → temp_* staging → main tables, progress via SignalR SmartInventoryHub.

9. Per-customer divergence (the branch problem)

~1,626 branches; 36 match develop-. The develop-<customer> convention has eroded into a mix of true tenant forks, environment variants (-prerelease/_staging/-Super-App), and ordinary feature branches misusing the prefix. BharatNet alone spawns 7 branches.

Customer branchFiles changedLines +/−AheadBehindMerge-baseFork age
develop-bharatnet1,052+157k / −115k1,3781662025-04-10~14 mo
develop-ACT451+98k / −2k64842026-02-27~3.5 mo
develop-airtel319+46k / −5k150442025-07-19~11 mo
develop-safaricom1,879+165k / −475k1721,6562024-03-04~27 mo

What actually diverges — genuine feature forking into core code, not just branding:

  • Forked core controllers/BL (e.g. LibraryController diverges in all four; ACT adds a whole MobileFormController +9,186 and BLOSPDynamicForm +5,591; BharatNet adds SurveyReportController +8,733; Airtel adds ZTE/Huawei/ESB vendor integrations).
  • Per-tenant DB schema — dozens-to-hundreds of dated customer-specific MigrationScripts/*.sql creating custom entities/attributes (ACT: 94 files).
  • Custom entities/dynamic forms are the dominant theme — customers needing different network-entity models is being solved by forking the form/controller stack.
  • Config/branding (Web.config conn strings/map URLs, logos/favicon/login UI, resource churn) is the minority of the diff but is unmanaged (even local dev paths like D:\…\GIT\ leak into customer branches).
  • No re-baselining discipline — Safaricom is 1,656 commits behind mainline (effectively abandoned); one customer = up to 7 branches.

Even the generic develop is contaminated: hardcoded customer columns iru_given_airtel, iru_given_jio, fiber_pairs_given_to_airtel in the shared cable-attribute write path (DACable.cs), and AppSettings["ClientName"] reads in MapReport.


10. Tech-debt & risk register (for the rewrite team)

#IssueEvidenceRewrite implication
1God classesDAMisc 4,862 LOC / 324 methods / 227 procs (new’d 67×); LibraryController 13,752; ReportController 12,860; Main.js ~34kDecompose Misc/Layer/User/WFMTicket/MapPrinter + Library/Report first
2No DI, per-call DbContext, no UoWRepository.cs news a DbContext per getter; 58 copy-paste singletonsDI + unit-of-work + transactions from day one
3Stringly-typed proc contractProcHelper reflection; ~1,200 sites; decimal→Double, unknown→VarcharTyped data layer; treat proc export as a migration project
4Logic hidden in DB536 PG functions, bodies not in repoExport & reverse-engineer procs before re-implementing
5Secrets in sourceplaintext creds in every *.config + datashare.incSecret manager / per-tenant config store; rotate all
6Massive copy-paste15+ Download*New/All report variants; …tt approval twins; .bak files shipped (ISP.bak.js 3,068 LOC)Config-driven reports/exports; delete dead code
7Security smells[Authorize] commented out in BOMBOQController; no CSRF; CORS *; AllowInsecureHttpSecurity baseline + review
8Library/version sprawl≥5 jQuery versions, 2 deck.gl versions, DevExtreme 170k LOCSingle modern frontend stack
9Branch-per-customer§9Multi-tenant config-not-code is the headline requirement
10In-memory report genfull DataTable before serializeStreaming/async exports
11No testsrepo-wideTDD from the start
12Naming/convention driftDA vs DL; MaintainenceCharges, DownloadBckup; BLJunctionBox has no DA (possibly dead); duplicate MainContextClean conventions; audit orphans

11. Implications for Lepton Infrastructure Cloud (mapping legacy → PRD principles)

PRD principleWhat the legacy provesConcrete rewrite guidance
Schema-driven extensibility (add a utility = config)layer_details + item_template_* + dynamic_controls already attempt this — but flag-sprawl + table-per-entity + branch-per-customer show it didn’t go far enoughMake custom entities/attributes/forms/reports first-class runtime config, multi-tenant-scoped. This single capability eliminates ~all customer branches.
Graph-native topologyTopology is implicit FK columns + splice/port tables resolved by PG functions; works but isn’t first-classModel nodes (equipment/closures) + edges (cables/fibers/ports) explicitly (PRD’s Apache AGE or equivalent); upstream/downstream/impact traces become native.
Spatial coreGeometry decoupled into *_master (sp_geometry, 4326), shipped as WKT stringsStore typed geometry(…,4326) on the entity; use EF-Core-spatial/NTS + GeoJSON at the API edge; stop WKT round-tripping. Collapse the ~5-table-per-entity sprawl.
Multi-tenant / config-not-code§9 — the dominant cost of the legacyTenant-scoped config, declarative auto-applied migrations, feature flags, theming/white-label, custom report builder. Single codebase, zero customer branches.
API-firstTwo OWIN OAuth APIs already exist; opaque tokens, no JWT, CORS *Clean API gateway, JWT/OIDC, per-tenant auth, versioned contracts.
AI-native operations (Vision doc)Logic locked in opaque procs; no event history; OTDR is metadata-onlyEvent-sourced asset history + a semantic graph are prerequisites for the agent/AutoML vision — neither exists today.
Pluggable integrationsSSO/SMS/OSS/ERP are bolted in per deployment, secrets in configConnector/plugin framework + secret manager; treat each IdP/SMS/OSS as a configured provider.

12. Open questions / what we still need to obtain

  1. The stored-procedure library (~536 fn_* bodies) — the real domain logic. Export from a live DB.
  2. The live DB schema — especially DDL for point_master/line_master/polygon_master and layer_details (not in repo).
  3. OLT/ODF modeling — confirm whether these are under FMS/Rack or genuinely absent.
  4. RoutingContext — is the routing/topology DB a separate physical database?
  5. BLJunctionBox — dead code, or does it call a differently-named DA?
  6. Customer-branch inventory — which develop-<customer> branches are live customers vs. abandoned; what each fork’s net delta over develop actually is (a per-branch deep-dive, separate from this study).
  7. Deployment Manager — the custom migration tool; how schema is actually versioned in production.

Addendum — companion documents & verified corrections (2026-06-16)

This study was the first pass. Three companion docs now extend it, and deeper code reads refined a few of its figures.

Companion documents (read alongside this one):

  • SmartInventory_Product_Specification.md — full module → submodule → feature spec of the generic product.
  • SmartInventory_Gaps_and_Improvement_Analysis.md — forward-looking improvement backlog + active security findings in the live product (committed auth backdoors, a hardcoded AES key protecting all PII/connection strings, live SQL-injection sites). Treat the security items as a live-product incident to remediate, not just “design out of the new platform.”
  • SmartInventory_Customer_Forks_Analysis.md — what the ~19 customer forks contain and the configurability primitives the new platform must ship.

Verified corrections to figures above (later reads override the original estimates):

  • Module codes: the licensing/feature gate set is 90+ (lstUserModule.Contains(...) incl. sub-feature codes), not “~45” as stated in §1/§5.5. The “45” was an undercount of distinct user-facing modules.
  • layer_details flags: 103 mapped boolean/config columns, not “~110” (§1/§4.2).
  • Tower entity: the main save path uses TowerMaster/BLTower/DATower; only one render path uses VaultMaster — so §4.1’s “Tower persists as VaultMaster” is only partially true.
  • OLT/ODF: confirmed there is no dedicated entity — OLT = attributes on EquipmentInfo; ODF = a database view only (§4.1 “unsure” resolved).
  • SmartSQ surface: SmartFeasibility on develop covers single/bulk FTTH + route-core + dark-fiber P2P only; the marketed FWA / P2P-wireless / P2MP / 4G / 3D-LOS feasibility is not present on develop (likely customer-specific or marketing-ahead-of-code).
  • Converge ERP: the SOAP/WCF integration lives in SmartInventoryServices/Connected Services (used by the mobile FEController), refining §7’s attribution.

Compiled 2026-06-16 from a read-only study of references/SmartInventory-3.0@develop. This is ground-truth for “what exists today” — pair it with the vision/PRD docs, which describe “where we’re going.”