* Guard Activity index template against missing client/staff nested data
The activity log API at Activity/Api/Admin.php:38-49 only injects a
nested 'client' or 'staff' key when the corresponding *_id is set
(via isset() which returns false for null). System events and
client-only events therefore have no 'client' key, while staff-only
events have no 'client' key.
Under strict_variables, '{% if event.client %}' (line 191) throws
"Key 'client' ... does not exist" for any event without a client.
Switch the conditional to event.client_id / event.staff_id (always
present as SQL columns) and add '|default("")' to the nested
event.client.email / event.client.name / event.staff.email / event.staff.name
accesses so deleted-but-referenced records render gracefully.
* Guard Security iplookup template against empty country/asn data
When the GeoIP or ASN lookup fails (IncompleteRecord from MaxMind), the
Service catches and substitutes [] for the missing data. Under
strict_variables, the empty mapping at record.asn / record.country
causes line 48 to throw "sequence/mapping is empty".
Twig's |default filter on a GetAttrExpression compiles to a safe
is-defined check, so it correctly falls through to the placeholder
when the underlying array is empty or the key is missing.
Verified:
- /admin/security/iplookup?ip=192.168.1.1 (private IP, empty asn)
renders the row with 'Unknown' ASN cells.
- /admin/security/iplookup?ip=8.8.8.8 still renders
'15169' / 'GOOGLE' / 'United States'.
* Initialize notes/rel arrays in Support toApiArray so templates render without errors
Two related issues surfaced under strict_variables on the admin support
ticket page:
1. toApiArray only set $data['notes'] inside the foreach loop over
ticket notes. Tickets without any notes therefore had no 'notes' key
and 'ticket.notes|length' in mod_support_ticket.html.twig:42 threw
'Key "notes" does not exist'.
2. _getRelDetails returned [] (empty array) when a ticket has no
related entity. mod_support_ticket.html.twig sets {% set task =
ticket.rel %} and then accesses task.task, task.type, task.status
etc. on the next lines. Any access into an empty mapping throws
under strict_variables.
Fixes:
- Service::toApiArray: always initialize $data['notes'] = [] for admin
identity so the key is present even when empty.
- Service::_getRelDetails: always return the base structure with all
fields (id, type, task, new_value, status) set to null when there
is no related entity. Skip the DB lookups for the non-rel case.
Template hardening (defense-in-depth, in case other code paths return
a different shape):
- mod_support_ticket.html.twig:42: 'ticket.notes|length' -> 'is defined and
ticket.notes|length'.
- mod_support_ticket.html.twig:222: 'ticket.notes' -> 'ticket.notes|default([])'.
- mod_support_tickets.html.twig:238: same is defined guard.
Verified on dev:
- /admin/support/ticket/1 renders without errors.
- API now returns rel as {id: null, type: null, ...} and notes: [] for
tickets without related data.
- 1777 local tests pass, PHPStan clean.
* Harden tests and add Twig/ToApi linters
* Remove redundant setAccessible calls in tests
* Update cspell.json word list
* Add UrlAwarePermissiveContainer & trim errors
* Add geoip stub and fix ParserFactory usage
* Enforce and apply parentheses for new expressions
Note
FOSSBilling is under active development and currently considered beta. Expect rough edges and limited support.
FOSSBilling is a free, open-source billing and client management system. It helps online service businesses automate invoicing, payments, and client communication. While it’s popular with web hosting providers, it also works well for software licensing, digital downloads, and subscription services.
Features
- Billing & Invoicing: automated invoices, reminders, and basic reporting.
- Client Management: a central place for client data and communication.
- Extensibility: extension-friendly architecture for integrations and custom features.
- Payments: support for multiple gateways.
- Translations: community-powered, multi-language interface.
- Responsive UI: usable on desktop and mobile.
- Security-focused: built with security best practices in mind.
Getting Started
Requirements
FOSSBilling runs on standard LAMP/LEMP stacks. For the latest system requirements (PHP version, extensions, database, etc.), see the official requirements.
Installation
Follow the step-by-step Getting Started guide.
Just exploring? Try the public demo.
Contributing
We welcome contributions from the community! We’re actively modernizing the codebase and there’s plenty to do.
- Read the contributor guide.
- Pick an item from the open issues.
- Open a PR when you’re ready.
If you prefer to start a conversation first, drop by the forum or say hello on Discord.
Star History
Not a developer? Starring the repository helps others discover the project.
License
FOSSBilling is released under the Apache 2.0 license. See LICENSE for details.
This project includes third-party work:
- Open Source Iconography by Pictogrammers under the Pictogrammers Free License.
Links
- Website: https://www.fossbilling.org/
- Documentation: https://docs.fossbilling.org/
- Discord: https://fossbilling.org/discord
- Twitter/X: https://twitter.com/FOSSBilling
