Wiki source code of Contents
Version 7.1 by Admin User on 2026/09/01 16:46
Show last authors
| author | version | line-number | content |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 | |||
| 4 | |||
| 5 | |||
| 6 | |||
| 7 | |||
| 8 | |||
| 9 | |||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | **ONEcount Fulfillment Module** | ||
| 14 | |||
| 15 | Site Licenses — User Guide | ||
| 16 | |||
| 17 | = Contents = | ||
| 18 | |||
| 19 | ~1. Overview | ||
| 20 | |||
| 21 | 2. How Site Licenses Work | ||
| 22 | |||
| 23 | 3. Creating a Site License | ||
| 24 | |||
| 25 | 4. Managing IP Ranges | ||
| 26 | |||
| 27 | 5. Session Management | ||
| 28 | |||
| 29 | 6. The User Experience | ||
| 30 | |||
| 31 | 7. Monitoring Active Sessions | ||
| 32 | |||
| 33 | 8. Reporting | ||
| 34 | |||
| 35 | 9. Troubleshooting | ||
| 36 | |||
| 37 | 10. Permissions | ||
| 38 | |||
| 39 | = 1. Overview = | ||
| 40 | |||
| 41 | Site licenses provide IP-based concurrent access for institutions such as libraries, universities, and corporate offices. An institution purchases a license for N concurrent seats, and anyone accessing gated content from the institution’s IP range gets transparent access — no login required, no forms to fill out — up to the concurrent seat limit. | ||
| 42 | |||
| 43 | Key characteristics: | ||
| 44 | |||
| 45 | * Access is determined by IP address, not by individual user accounts | ||
| 46 | * Concurrent sessions are limited to the purchased seat count | ||
| 47 | * Sessions are maintained by a heartbeat mechanism — if a user leaves, their seat is automatically released after a configurable timeout (default: 30 minutes) | ||
| 48 | * When all seats are occupied, new visitors see a branded “seats full” message | ||
| 49 | * Each seat is represented by a synthetic OCID for reporting purposes | ||
| 50 | |||
| 51 | [[image:fulfillment-site-licenses_386f6176b5b0bbbe.png||height="430" width="586"]] | ||
| 52 | |||
| 53 | //The Site Licenses list showing three demo institutions with concurrent seat counts and statuses.// | ||
| 54 | |||
| 55 | In this example, Springfield Public Library has 15 concurrent seats (active), Metro University has 50 seats (active), and Horizon Aviation Museum is a cancelled license with 5 seats. | ||
| 56 | |||
| 57 | = 2. How Site Licenses Work = | ||
| 58 | |||
| 59 | == 2.1 Access Flow == | ||
| 60 | |||
| 61 | When a visitor accesses a page with gated content, the following happens: | ||
| 62 | |||
| 63 | * 1. The ONEcount widget (oc.min.js) loads and sends an access check request | ||
| 64 | * 2. The gating layer checks the visitor’s IP against all active site license IP ranges | ||
| 65 | * 3. If a match is found, the system checks for available concurrent seats | ||
| 66 | * 4. If a seat is available, the visitor is silently assigned a synthetic identity and granted access | ||
| 67 | * 5. The widget starts a heartbeat timer to keep the session alive | ||
| 68 | * 6. When the visitor leaves (closes browser, navigates away), the seat is released | ||
| 69 | |||
| 70 | == 2.2 Synthetic Identities == | ||
| 71 | |||
| 72 | Each concurrent seat maps to a pre-created synthetic user in the ONEcount database. These users have names like “Springfield Library, Seat 1” and internal email addresses like “sl-42-seat-1@sitelicense.internal.” They have real subscription records, which means they appear naturally in all standard reports. | ||
| 73 | |||
| 74 | //Synthetic users are created automatically when the site license is created. You do not need to create them manually.// | ||
| 75 | |||
| 76 | == 2.3 Session Lifecycle == | ||
| 77 | |||
| 78 | Sessions are tracked in Cassandra with a Time-To-Live (TTL). The TTL is set to the session_ttl value on the license (default: 1800 seconds / 30 minutes). Every heartbeat from the widget resets this TTL, keeping the session alive. If no heartbeat arrives within the TTL window, the session automatically expires and the seat becomes available. | ||
| 79 | |||
| 80 | Additionally, when a user closes the browser tab or navigates away, the widget attempts to release the seat immediately using the browser’s sendBeacon API. This provides faster seat turnover in normal usage. | ||
| 81 | |||
| 82 | = 3. Creating a Site License = | ||
| 83 | |||
| 84 | Navigate to Fulfillment › Site Licenses. Click the red “Create Site License” button to open the creation modal. | ||
| 85 | |||
| 86 | [[image:fulfillment-site-licenses_8e8e80905336a638.png||height="411" width="586"]] | ||
| 87 | |||
| 88 | //The Create Site License modal with institution name, seat count, product-or-package selection, and initial IP range.// | ||
| 89 | |||
| 90 | |**Field**|**Required**|**Description** | ||
| 91 | |**Institution name**|Yes|Display name (e.g., “Springfield Public Library”) | ||
| 92 | |**Purchaser OCID**|Yes|The OCID of the billing contact at the institution | ||
| 93 | |**Concurrent seats**|Yes|Maximum number of simultaneous users | ||
| 94 | |**Product or Package**|Yes|Select a product or package from the dropdown (grouped by type) | ||
| 95 | |**Term**|Yes|Select the term — cascades from the selected product or package | ||
| 96 | |**Publication**|No|The fulfillment publication (for magazine content) | ||
| 97 | |**Start date**|Yes|When the license becomes active | ||
| 98 | |**End date**|No|When the license expires (empty = perpetual) | ||
| 99 | |**IP range (CIDR)**|No|Initial IP range in CIDR notation. More can be added after creation. | ||
| 100 | |||
| 101 | When you create the license, the system automatically: | ||
| 102 | |||
| 103 | * Creates N synthetic users named “[Institution], Seat 1” through “[Institution], Seat N” | ||
| 104 | * Creates subscription records for each synthetic user | ||
| 105 | * Grants product access (user_product entries) so the gating layer recognizes them | ||
| 106 | |||
| 107 | = 4. Managing IP Ranges = | ||
| 108 | |||
| 109 | Each site license can have multiple IP ranges. Ranges are specified in CIDR notation: | ||
| 110 | |||
| 111 | |**Format**|**Example**|**Matches** | ||
| 112 | |**Single IP**|192.168.1.100|Exactly one IP address | ||
| 113 | |**Subnet /24**|192.168.1.0/24|192.168.1.0 through 192.168.1.255 (256 addresses) | ||
| 114 | |**Subnet /16**|10.0.0.0/16|10.0.0.0 through 10.0.255.255 (65,536 addresses) | ||
| 115 | |**Larger subnet**|172.16.0.0/12|172.16.0.0 through 172.31.255.255 | ||
| 116 | |||
| 117 | [[image:fulfillment-site-licenses_4a8d67282ca4569a.png||height="430" width="586"]] | ||
| 118 | |||
| 119 | //Springfield Public Library detail page showing IP ranges (Main branch /24, Eastside annex /28), active sessions, and synthetic seats.// | ||
| 120 | |||
| 121 | In this example, Springfield Public Library has two IP ranges configured: 198.51.100.0/24 for the main branch (256 addresses) and 198.51.101.0/28 for the Eastside annex (16 addresses). Each range shows the computed start and end IP and an optional label. | ||
| 122 | |||
| 123 | IP ranges are managed from the site license detail page. Click the “+ Add” button to add a new range, or the × button to remove an existing one. | ||
| 124 | |||
| 125 | //If an IP matches multiple site licenses, the system uses the most specific match (narrowest IP range).// | ||
| 126 | |||
| 127 | = 5. Session Management = | ||
| 128 | |||
| 129 | == 5.1 Heartbeat Configuration == | ||
| 130 | |||
| 131 | The detail page header shows the heartbeat and session TTL values for the license. In the Springfield Public Library example: | ||
| 132 | |||
| 133 | * Heartbeat interval: 120 seconds — the widget pings every 2 minutes | ||
| 134 | * Session TTL: 1800 seconds (30 minutes) — sessions expire after 30 minutes without a heartbeat | ||
| 135 | |||
| 136 | |**Parameter**|**Default**|**Description** | ||
| 137 | |**heartbeat_interval**|120 seconds|How often the widget pings to keep the session alive | ||
| 138 | |**session_ttl**|1800 seconds (30 min)|How long a session persists without a heartbeat before auto-expiry | ||
| 139 | |||
| 140 | These values are set per-license and can be adjusted based on the institution’s needs. A shorter session_ttl frees seats faster but may cause disruptions for slow readers. A longer interval reduces server load but delays seat release for idle users. | ||
| 141 | |||
| 142 | == 5.2 Seats Full Message == | ||
| 143 | |||
| 144 | When all concurrent seats are occupied, new visitors see a full-screen overlay with a customizable message. The default message is: | ||
| 145 | |||
| 146 | “//All N seats for [Institution Name] are currently in use. Please try again later.”// | ||
| 147 | |||
| 148 | You can customize this message per-license via the seats_full_message field. The page auto-retries every 30 seconds. | ||
| 149 | |||
| 150 | = 6. The User Experience = | ||
| 151 | |||
| 152 | The site license experience is designed to be completely transparent to the end user: | ||
| 153 | |||
| 154 | * No login form is displayed | ||
| 155 | * No registration is required | ||
| 156 | * No ONEcount branding is shown | ||
| 157 | * Content loads normally as if it were unprotected | ||
| 158 | * The only user-visible moment is when seats are full — a branded overlay appears | ||
| 159 | |||
| 160 | Behind the scenes, the widget sets session cookies (~_~_oc_sl_session, ~_~_oc_sl_id, ~_~_oc_sl_hb) to maintain the session. These are automatically managed and do not require user interaction. | ||
| 161 | |||
| 162 | = 7. Monitoring Active Sessions = | ||
| 163 | |||
| 164 | The site license detail page shows active sessions in real-time (visible in the “Active Sessions” card). For each session, you can see: | ||
| 165 | |||
| 166 | * Seat number | ||
| 167 | * Synthetic OCID | ||
| 168 | * Visitor’s IP address | ||
| 169 | * Session start time | ||
| 170 | * Last heartbeat time | ||
| 171 | |||
| 172 | You can force-release a session from this page if needed (e.g., if a session appears stuck). Click the “Release” button next to the session. The “Refresh” button updates the session list. | ||
| 173 | |||
| 174 | = 8. Reporting = | ||
| 175 | |||
| 176 | Site license seats are represented by synthetic OCIDs with real subscriptions. They flow through all standard fulfillment reports: | ||
| 177 | |||
| 178 | * RPT-01 (Circulation) — Synthetic OCIDs are counted in their classification bucket | ||
| 179 | * RPT-09 (Adds & Removals) — Reason codes SITE_LICENSE_NEW, SITE_LICENSE_EXPIRED, SITE_LICENSE_CANCELLED track lifecycle events | ||
| 180 | * RPT-19 (Mail File) — Site license seats typically do not receive mail (no physical address), but they appear in the serve log for audit purposes | ||
| 181 | |||
| 182 | The subscription_source field on the serve log is tagged as “site_license” for these OCIDs, enabling easy filtering in custom reports. | ||
| 183 | |||
| 184 | = 9. Troubleshooting = | ||
| 185 | |||
| 186 | |**Symptom**|**Likely Cause**|**Resolution** | ||
| 187 | |**Users see login form instead of transparent access**|IP range not configured or doesn’t match the visitor’s IP|Check the IP ranges on the license detail page. Verify the visitor’s public IP matches a configured range. | ||
| 188 | |**Seats fill up faster than expected**|session_ttl too long; idle sessions holding seats|Reduce session_ttl (e.g., to 900 seconds / 15 min) | ||
| 189 | |**Sessions don’t release when users leave**|Browser doesn’t support sendBeacon or blocks it|Normal — sessions will auto-expire after session_ttl. Consider reducing the TTL. | ||
| 190 | |“**Seats full” when seats should be available**|Stale sessions in Cassandra|Force-release sessions from the admin detail page. Sessions also auto-expire. | ||
| 191 | |**Synthetic users not appearing in reports**|Migration not applied|Apply fulfillment/sql/034_site_license.sql and fulfillment/cql/010_site_license_session.cql | ||
| 192 | |||
| 193 | = 10. Permissions = | ||
| 194 | |||
| 195 | Site license management requires the FULFILLMENT_SITE_LICENSE_MANAGE permission module. Creating site licenses additionally requires FULFILLMENT_SETUP. Superadmin users automatically have access to all functions. | ||
| 196 | |||
| 197 | = Appendix: Navigation = | ||
| 198 | |||
| 199 | All three subscription model features are accessible from the Fulfillment section of the admin sidebar: | ||
| 200 | |||
| 201 | [[image:fulfillment-site-licenses_737296447e02486d.png||height="430" width="586"]] | ||
| 202 | |||
| 203 | //The Fulfillment sidebar menu showing Gift Subscriptions, Group Licenses, and Site Licenses navigation entries.// |