# Business rules — procon8

Evidence date: 2026-10-06. Source: `git@bitbucket.org:overdrive/procon8.git` at `45e5ee9f` (`master`).

No business-rules document existed in the repository or in Silicon Ark. Rules below are taken from project code, from config that always runs, or from vendored code that changes who can do what. Vendor marketing text is not treated as a rule of this organisation.

Rules enforced only when a plugin is active are marked that way. Active plugins are a database setting and are **Unknown** unless noted.

Secrets are not copied here.

## Identity

### BR-001 — Site is connected as Discover

**Implemented.** WordPress uses database name `Discover`, database user `Discover`, charset `utf8mb4`, empty collation, table prefix `wp_`.

The host is an Amazon RDS cluster endpoint in `eu-west-1`. The cluster identifier begins with `discoverkasi-cluster`. The exact hostname is in `wordpress/wp-config.php`.

Evidence: `wordpress/wp-config.php`.

### BR-002 — Discover Kasi is the name used when the WordPress tree replaced the static site

**Inferred** from labels, not from a brand guide:

- Commit `52b6bc59` message: "Discover kasi wordpress".
- Deleted template `s3bucket.json` tag `OWNER` = `DiscoverKasi` and `SYSTEM` = `Procon8`.
- Historical PHP logs use the account path `/home/discoverikasico/public_html/` and timezone `Africa/Johannesburg`.

There is no logo file, style guide, or about-page copy in git that states the public name. **Unknown / Requires Confirmation** whether the live site title is Discover Kasi.

The Listable demo strings "Discover The City Gems" and "Discover something nice" are theme sample data (`themes/listable/inc/import/demo-data/demo_data.php` and `inc/widgets.php`). They are not evidence of this site's name.

### BR-003 — Procon8 is the repository and the AWS application name

**Implemented** as names in `elasticbeanstalk.json`: description "Deploy the Procon8 application to Elastic Beanstalk"; default application `Dev-procon8`; default environment `dev-Procon8`; default key pair `dev-procon8`.

**Unknown / Requires Confirmation** whether Procon8 is the customer, the agency, or only the stack name. Silicon Ark uses PROCON8 as a company name on other products. This repository does not say they are the same thing.

### BR-004 — The earlier public page was a personal portfolio

**Implemented, then removed from `master`.** Immediately before commit `52b6bc59`, `test/index.html` had title "Akhona Booi - Model / Brand Manager", headings "Portfolio" and "About Me", and an Instagram link to `sparkling_ako`.

That page is not the WordPress product. It is historical content of this repository. The `Dev` branch tip still has a static page titled "My Blog", which is a third, earlier page.

## What visitors see

### BR-005 — Home category counts are hidden

**Implemented.** `.home span.category-count` is `display: none !important` in the child theme.

Evidence: `wordpress/wp-content/themes/listable-child-master/style.css`.

This rule runs only when Listable Child is the active theme. Activation is **Unknown**.

### BR-006 — WooCommerce subcategory counts can be removed

**Vendor rule, conditional.** Plugin "Hide products count" returns empty HTML from `woocommerce_subcategory_count_html`.

Evidence: `wordpress/wp-content/plugins/hide-products-count.php_/hide-products-count.php`.

Active only if that plugin is enabled. **Unknown**. The odd directory name does not remove the plugin header.

### BR-007 — Listing search needs JavaScript

**Vendor copy, conditional.** The hero job-filter template says listings cannot be viewed when JavaScript is disabled.

Evidence: `themes/listable/job_manager/job-filters-hero.php`.

Applies when that template is used (WP Job Manager active and the hero filter rendered). **Unknown** if that template is on the home page.

### BR-008 — Empty listing searches say "No results"

**Vendor string, conditional.** Listable overrides `no_job_listings_found` with "No results".

Evidence: `themes/listable/functions.php`.

### BR-009 — A new listing is either public immediately or held for approval

**Vendor behaviour, conditional.** `job-submitted.php` prints one of two messages: the listing can be viewed now, or it will be visible once approved. WP Job Manager chooses the message from its moderation setting.

The setting is not in git. **Unknown / Requires Confirmation** which mode this site uses.

### BR-010 — Pretty permalinks

**Implemented in `.htaccess`.** Non-existent files and directories rewrite to `/index.php`.

Evidence: `wordpress/.htaccess`.

The WordPress permalink option that matches this file is a database setting. **Inferred** that the site used pretty permalinks when the file was exported. Whether the file is inside the deploy zip is a separate deployment question (`zip wordpress/*` skips names that start with `.`).

## Who may see and edit what

### BR-011 — WordPress roles

**Implemented** by WordPress core. Standard roles apply. The child theme does not add a role or a capability check.

Who has an account is **Unknown**.

### BR-012 — Administrators must use SSL

**Implemented.** `FORCE_SSL_ADMIN` is true.

Behind a TLS-terminating load balancer, `HTTP_X_FORWARDED_PROTO` equal to `https` sets `$_SERVER['HTTPS']` to `on`.

Evidence: `wordpress/wp-config.php`.

### BR-013 — Listing owners manage their own listings

**Vendor rule, conditional** on WP Job Manager. The dashboard template shows the current user's listings and offers edit, delete, relist, and mark filled / mark not filled, with nonces on the state-changing actions.

Evidence: `themes/listable/job_manager/job-dashboard.php`.

The plugin's own capability map decides who may submit listings. That map is not customised in the child theme. **Unknown** which roles can submit.

### BR-014 — Menus can be limited by role

**Vendor rule, conditional** on Nav Menu Roles 1.8.6. No menu items are stored in git, so no concrete menu rule can be stated.

### BR-015 — Debug output is off

**Implemented.** `WP_DEBUG` is false. The Beanstalk PHP ini file sets `display_errors` to Off.

Evidence: `wp-config.php`, `wordpress/.ebextensions/php-settings.config`.

## Commerce and bookings

### BR-016 — More than one shop and more than one booking plugin are vendored

**Implemented as files. Not a stated business rule.** The tree contains both WooCommerce and Ecwid, plus WooCommerce Bookings, accommodation bookings, and four other booking plugins.

No code in the child theme chooses among them. Which catalogue, currency, tax, and booking policy apply is **Unknown / Requires Confirmation**. Do not treat the presence of a plugin as a decision that it is the live shop.

### BR-017 — Paid listing packages and bookmarks are templated but not installed

**Inferred.** Listable includes `wc-paid-listings/package-selection.php` and bookmark templates. The plugins those templates call are not under `wp-content/plugins/`.

There is no evidence in git that listing owners must pay to publish. **Unknown**.

## Deployment and environment rules

### BR-018 — Master deploys the WordPress tree; Dev deploys the old static site

**Implemented.**

- On `master`, branch `master` zips `wordpress/*` and uploads S3 key `wordpress.zip` (same key every time, so the object is overwritten).
- On `origin/Dev`, branch `Dev` zips `test/*` and uploads a new key `{APPLICATION_NAME}/{timestamp}`.

The `Dev:` step inside the `master` pipeline file zips `Dev/*`. That directory is not on `master` or on `Dev`. It does not run when `master` is pushed. If that file were the pipeline on the `Dev` branch, the zip step would not match the tree. The `Dev` branch currently carries a different pipeline file, so this is a latent mismatch, not the file Bitbucket would use for `Dev` today.

Evidence: `bitbucket-pipelines.yml` on each branch, `beanstalk_deploy.py` on each branch.

### BR-019 — Deploy credentials come from the pipeline, not from git

**Documented** in `README.md`. Required variables: `AWS_SECRET_ACCESS_KEY`, `AWS_ACCESS_KEY_ID`, `AWS_DEFAULT_REGION`, `APPLICATION_NAME`, `APPLICATION_ENVIRONMENT`, `S3_BUCKET`.

The README says the IAM user should have `AWSElasticBeanstalkFullAccess`, and that access should be limited to the relevant resources. The second sentence is guidance. The managed policy named is broad. The values are not in the repo.

### BR-020 — A failed deploy stops the pipeline

**Implemented.** `beanstalk_deploy.py` calls `sys.exit(1)` when S3 upload, application-version create, or environment update throws or returns a non-200 on version create. It does not roll back a half-applied environment update. It waits a fixed 5 seconds between version create and deploy, not until Beanstalk reports Ready.

### BR-021 — Environment sizes in the CloudFormation template

**Implemented in the template. Not proven to be applied.**

- `BucketENV`: `dev`, `int`, `qa`, or `prod`. Default `dev`.
- Instances: minimum 1, maximum 6, default type `t2.micro`.
- Environment type `LoadBalanced`, load balancer type `application`.
- Solution stack: 64bit Amazon Linux 2018.03 v2.8.9 running PHP 7.2.
- Instance security group allows TCP 80 from `0.0.0.0/0`.
- Default source object key `test.zip`, which is not the pipeline key `wordpress.zip`.

Evidence: `elasticbeanstalk.json`.

### BR-022 — Instance role in the template can do anything

**Implemented in the template.** `RolePolicies` allows `Action` `*` on `Resource` `*`.

That is what the file says. Whether this stack was deployed is **Unknown / Requires Confirmation**. It should be reviewed before anyone treats the template as the live policy.

### BR-023 — HTTPS listener is world-open on 443

**Implemented in `.ebextensions`.** The load balancer security group allows TCP 443 from `0.0.0.0/0` and egress TCP 80 to `0.0.0.0/0`. The listener uses an ACM certificate in `eu-west-1`. Health checks request `/readme.html` over HTTP port 80.

Evidence: `wordpress/.ebextensions/loadbalancer-sg.config`.

### BR-024 — Shared uploads via EFS are not a current rule

**Removed.** On 2019-08-02 the EFS config was deleted. It had mounted `EFS_NAME` from the Beanstalk environment properties and symlinked `/var/www/html/wordpress/wp-content/uploads` to `/mnt/efs/uploads`.

The current tree does not mount shared disk for uploads. S3 offload is available if the plugin is configured. **Unknown** which storage production uses.

### BR-025 — PHP limits

**Implemented in `.ebextensions`, if that file is applied.**

- Document root `/wordpress`.
- `memory_limit` 256M.
- `max_execution_time` 60.
- `allow_url_fopen` On.
- `display_errors` Off.
- `zlib.output_compression` Off.
- `composer_options` is the literal `vendor/package`. No `composer.json` at the WordPress root was found. **Inferred** that this value is an unused sample setting.

## What is not a rule

- Theme demo copy is not site content.
- Plugin directories are not proof of an enabled feature.
- The README's "copy this script into your project" steps describe the sample, not a requirement that other Overdrive projects use this repo.
