* refactor: Replace var with let/const in JavaScript files
- Replace var with let for variables that are reassigned
- Replace var with const for variables that are never reassigned
- Modernize manage_tables.js and nominatim.autocomplete.js
- Skip third-party libraries (imgpreview.full.jquery.js, clipboard.min.js)
Closes#4491
* refactor: Replace var with let/const in inline JavaScript
- Fixed CodeRabbit review: changed enable_actions and load_success
from const to let in manage_tables.js (they are reassigned in init)
- Replaced all var declarations in inline JavaScript in Views with
let (for reassigned) or const (for never reassigned)
- Modernized 48 additional files with inline JavaScript
* refactor: Replace var with let/const in remaining JS files
- Modernized gulpfile.js: 3 var declarations replaced
- Modernized app/Views/errors/html/debug.js: all var declarations replaced
- Used const for never-reassigned, let for reassigned variables
* fix: Replace remaining var declarations in Views
- Changed var to const in sales/register.php
- Changed var to const in configs/receipt_config.php
These were missed in the initial pass.
* fix: Replace remaining var declarations in gulpfile.js
- Converted 12 remaining var declarations to const
- All variables are function-scoped and never reassigned
- Complete coverage for this file now
* fix: Address CodeRabbit review comments
- items/manage.php: Remove duplicate let declaration for start_date
(partial/daterangepicker already declares it)
- header_js.php: Escape CSRF hash in JavaScript context
- tax_jurisdictions.php: Fix mismatched selector (remove_tax_jurisdictions
-> remove_tax_jurisdiction)
* style(views): Replace var with let/const and fix comment casing
- Convert var to let in items/manage.php for JS modernization
- Capitalize \"Submit\" in validation comments across tax view files
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
* fix: wrap postSave() in single transaction for atomicity
- Remove internal transaction from Item_taxes->save_value() to allow controller-level transaction
- Wrap entire save sequence (item, taxes, quantities, inventory, attributes) in single transaction
- Ensure all operations succeed or all fail together
- Prevents partial writes when saveItemAttributes() fails after item/tax/quantity saves succeed
Fixes#4474
* fix: Use explicit transBegin/transCommit/transRollback for atomicity
- Replace transStart/transComplete with transBegin/transCommit/transRollback
- Check all success conditions before committing
- Explicit rollback on failure
Address CodeRabbit review feedback
* refactor(items): rename postSave locals to camelCase per PSR-12
Convert snake_case variables to camelCase in postSave() and related
item-save logic to match project naming convention for new methods.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(login): skip auth validation on new install to allow migration
On fresh installs with no DB version, login validation would fail
before migrations could run. Check MY_Migration::getCurrentVersion()
and bypass credential check when no version exists.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(login): distinguish DB unavailable from empty install
`getCurrentVersion()` previously returned `int` with 0 used for both
\"empty database\" and \"DB connection failure\". This conflated two
distinct states, causing login to skip auth when DB was unreachable.
Changes:
- Return type widened to `?int`: null = DB unavailable, 0 = confirmed
empty DB (new install), positive int = migrated
- Login controller now returns 503 on null (DB error) before checking
isNewInstall
- isNewInstall gate now uses `=== 0` instead of falsy check
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(login): return 503 JSON response when DB connection unavailable
Extract getCurrentVersion() before building data array to distinguish
null (connection failure) from 0 (new install). Return early with JSON
503 when DB is unreachable instead of rendering broken view.
Update return type hint to include ResponseInterface.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: jekkos <jekkos@users.noreply.github.com>
- Rename get_giftcard_id to getGiftcardId (PSR-12 camelCase)
- Fix return type from bool to int|false
- Replace loose == with strict === comparison
- Update all call sites in Giftcards controller and Sale model
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
* Add `reference_code` to sale payment queries and group by statements
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` controller to improve payment handling readability and replace snake_case with camelCase variables
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Add missing translations for `Sales` language file and include new keys like `must_enter_rrn` and `reference_code`
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` payment handling to use camelCase and extend `addPayment` with `referenceCode` support
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` models, controllers, and libraries to adopt camelCase naming conventions and improve readability
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Add translations and updates for `must_enter_reference_code` and `reference_code` across language files and update `Sales` controller to replace `must_enter_rrn` with the new key
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(sales): add reference code input and payment type helper
- Add `get_reference_code_payment_types()` to locale_helper as single
source of truth for card-requiring payment types
- Add reference code row to register view, shown/hidden via JS based
on selected payment type
- Fix payment type dropdown width to 100% for consistent layout
- Add min-width to payment buttons and right-padding to button group
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(config): add payment reference code length configuration
- Add payment_reference_code_min and payment_reference_code_max fields
to Config controller save logic
- Add translation keys for reference code length limits across all
language files (min/max label + section header)
- Align array key formatting in Config controller for readability
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* style(lang): normalize string delimiters to single quotes across all language files
Convert double-quoted array keys and values to single quotes in all
app/Language/*/Config.php and app/Language/*/Sales.php variants.
No translation content changed — formatting only.
Also add Localization section to AGENTS.md documenting language file
conventions for new keys and fallback behavior.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(lang): add payment reference code length translations
Add localized strings for payment_reference_code_length_limits,
payment_reference_code_length_max_label, and
payment_reference_code_length_min_label across all supported locales.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* test(config,sales): add payment reference code min/max validation tests
- Add baseLocalePayload() helper in ConfigTest for postSaveLocale tests
- Add testSaveLocale_AcceptsValidReferenceCodeMinMax and related boundary tests
- Add Sale_libPaymentTest for payment reference code validation in Sale_lib
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(sales): add type-specific validation for amount_tendered
Gift card payments use amount_tendered as giftcard number (integer);
cash/other payments require decimal_locale format. Apply correct
validation rule per payment type instead of generic required.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(lang): replace self-closing </br> with <br> in all locales
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(sales): use configurable precision in discount comparison
Replace hardcoded precision 2 with totals_decimals() when comparing
discount against item total via bccomp/bcmul, so discount validation
respects the configured decimal precision setting.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(lang): correct Azerbaijani translations in Config.php
Replace placeholder/mismatched strings with accurate translations:
- email_mailpath, email_smtp_pass, invoice_email_message
- number_locale_invalid/required, receipt_template
- reward_configuration, right, tax_decimals, theme
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(sales): add reference code support to payment edit flow
- Add reference_code field to new payment row in sale edit form
- Persist reference_code on insert in Sale model
- Validate reference_code_new in Sales controller using configurable min/max length rules
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(lang): add Georgian (ka) language stubs for Config and Sales
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Match the fallback maximum reference_code length to the maximum of the field in the db
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Bug fixes
- Add validation of UI settings to prevent overridden values from being passed.
- Correct maximum value in JS for payment_reference_code maximum length to 40.
- Fix bug causing copy_entire_sale() to incorrectly copy the reference code and cash_adjustment
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
* Fix overly lenient date validation
- In the past date validation would roll over dates that didn't exist into the next month. Now they return an error.
Signed-off-by: objec <objecttothis@gmail.com>
* Refactor naming
- Refactor parameter
- Refactor function name.
Signed-off-by: objec <objecttothis@gmail.com>
* Add unit tests for LocaleHelper
Signed-off-by: objec <objecttothis@gmail.com>
* Remove files from being tracked.
Signed-off-by: objec <objecttothis@gmail.com>
---------
Signed-off-by: objec <objecttothis@gmail.com>
* fix(security): Fix DOMPDF RCE and customer email sanitization
- Disable isPhpEnabled in DOMPDF to prevent RCE via embedded PHP in HTML
- Disable isRemoteEnabled to prevent SSRF attacks
- Add email validation and sanitization in CSV import (FILTER_SANITIZE_EMAIL, FILTER_VALIDATE_EMAIL)
- Reject invalid email formats during customer import
* fix(security): Escape email addresses in mailto() to prevent XSS
Email columns in bootstrap tables had escaping disabled (line 52) and
mailto() function doesn't escape its parameters. This fix escapes email
addresses before passing to mailto() in:
- get_person_data_row() (employees)
- get_customer_data_row() (customers)
- get_supplier_data_row() (suppliers)
Attack vector: Malicious email via CSV import renders XSS in table view.
* test(security): Add tests for customer CSV import email validation
Tests cover:
- Valid email acceptance
- Invalid email rejection with row-specific error
- XSS payload sanitization in email field
- Mixed valid/invalid email handling
- Email with special characters sanitization
Verifies fixes for customer email import vulnerability.
* fix(security): Allow empty email addresses in customer import
- Empty emails are now allowed (customers may not have email addresses)
- Validation only applies when email is non-empty
- Added test case for empty email acceptance
This fixes a regression where FILTER_VALIDATE_EMAIL rejected empty
strings, breaking imports for customers without email addresses.
---------
Co-authored-by: Ollama <ollama@steganos.dev>
- Add 'show_in_search' and 'show_in_search_visibility' to all language files
- Translated: de-DE, es-ES, fr, it
- Placeholder English for remaining languages (awaiting translation)
This ensures the SHOW_IN_SEARCH attribute flag works in all locales.
- sanitizeSortColumn expects nested array format [['col' => 'label'], ...]
- Reuse item_headers() as base and add attribute columns
- This maintains DRY principle by not redefining columns twice
- When sorting by attribute column, determine the attribute type
- Use attribute_decimal for DECIMAL type
- Use attribute_date for DATE type
- Use attribute_value for TEXT/DROPDOWN/CHECKBOX types
- This ensures numeric and date attributes sort correctly instead of lexicographically
Fixes CodeRabbit feedback on PR #4442.
- Update regex pattern to support multi-word attribute names (e.g., 'aspect ratio')
- Rename $includeDeleted to $matchDeleted for clarity (matches deleted flag value)
- Add check to skip attributes not in caller-provided definitionIds filter
- Use Unicode pattern modifier 'u' for international character support in attribute names
This addresses CodeRabbit's feedback on PR #4442.
- Rename methods to camelCase (PSR-12): parseAttributeSearch, searchByAttributes, searchByAttributeValue, getAttributeSortDefinitionId
- Rename variables to camelCase (PSR-12)
- Add DATE attribute search support in searchByAttributeValue
- Fix get_definitions_by_flags to request typed payload (second param true)
- Handle both array and string return shapes for definition info
- Fix term-only search to merge with attribute matches instead of replacing
- Use strict emptiness checks (=== '' instead of empty())
- Sanitize definition_ids before SQL interpolation (array_map intval)
- Include DATE in attribute search conditions
- Fix PHPDoc comment format in item_sort_columns() helper
- Remove duplicate blank line after properties in Item model
- Remove unused variable assignment in Items controller
- Add item_sort_columns() helper function in tabular_helper.php
- Helper returns all sortable columns including dynamic attribute IDs
- Remove duplicate sanitizeSortColumnAttribute method from Items controller
- Remove unused ALLOWED_SORT_COLUMNS constant from Item model
- Reuses existing sanitizeSortColumn method from Secure_Controller
- Add Item::ALLOWED_SORT_COLUMNS constant for allowed sort columns
- Use constant in sanitizeSortColumnAttribute() instead of inline array
- Enables reuse across the codebase for sort column validation
Phase 3 - Multi-attribute Search:
- Add parse_attribute_search() method to parse search syntax like
'color: blue size: large' or 'color:blue AND size:large'
- Update search_by_attributes() to support AND/OR logic for multiple
attribute queries
- Add search_by_attribute_value() private method for single value search
Phase 4 - Sort by Attribute Columns:
- Add get_attribute_sort_definition_id() method to detect attribute
column sorting
- Update Item::search() to join attribute tables when sorting by
attribute columns
- Update tabular_helper to make attribute columns sortable
- Add sanitizeSortColumnAttribute() method in Items controller to
validate attribute definition IDs as sort columns
Fixes#2722 - sorting by attribute columns now works
Phase 2 implementation:
- Add SHOW_IN_SEARCH constant (value 8) to Attribute model
- Update Items controller to include searchable attributes when
search_custom filter is enabled
- Add language strings for the new visibility flag
- Update Attributes controller to include new flag in form
This allows attributes to be searchable even if they are not
displayed in the items table, addressing issue #2919.
Fixes#2919
- Add new search_by_attributes() method that returns matching item_ids
- Refactor search() method to use subquery approach instead of HAVING LIKE
- Fix pagination count issue (#2819) - get_found_rows() now returns correct count
- Enable combined search (attributes OR regular fields)
- GROUP_CONCAT still used for display but removed from search/count logic
- Fixes#2407 - multi-attribute search now works correctly
Related: #2819, #2407, #2722, #2919
* fix: tax rate inputs blank with comma-decimal locales
The to_tax_decimals() function returns locale-formatted values
(e.g. "18,00" for comma-decimal locales like fr_FR, de_DE).
Browsers reject comma-decimal values in <input type="number">
and render the field blank.
Use raw float value instead - PHP serializes floats with period
decimal regardless of locale. The parse_tax() on the save side
already handles locale-aware parsing, so round-tripping works
correctly.
Fixes#4553
Regression from commit 42ba39d29
* fix: tax rate input locale handling - save path
The display fix (using (float) instead of to_tax_decimals()) was
correct but incomplete. The save path in Config.php also needed
fixing because parse_tax() misinterprets dot-decimal values from
type="number" inputs when locale uses comma as decimal separator.
Root cause: Browsers submit type="number" inputs as dot-decimal
(e.g., "5.5") regardless of locale. With comma-decimal locales
like de_DE, parse_tax() treats the dot as thousands separator,
causing 5.5 to be saved as 5.
Fix: Replace parse_tax() with direct (float) cast for these
inputs since type="number" already guarantees dot-decimal format.
Includes tests for tax rate handling with various decimal values.
Fixes#4553
* revert: remove type=number from tax rate inputs
Resolution from PR #4555 review: Revert to text inputs for locale-specific
tax rate fields.
The type='number' attribute was added in commit 42ba39d29, but it caused
issues with locale-specific decimal separators. Browsers submit type='number'
inputs as dot-decimal regardless of locale, which breaks comma-decimal locales.
Solution: Revert to text inputs which use to_tax_decimals() for display
and parse_tax() for saving, correctly handling locale-specific formatting.
Changes:
- tax_config.php: Remove type='number', step, min, max attributes
- tax_config.php: Restore to_tax_decimals() for value display
- Config.php: Restore parse_tax() for tax rate parsing
- ConfigTest.php: Remove tests added for the type='number' approach
Fixes#4553
---------
Co-authored-by: Ollama <ollama@steganos.dev>
* Properly replace key in config file when encryption key is updated
This fixes a break caused if there is a commented out key in the .env. It's a more robust replacement.
Signed-off-by: objec <objecttothis@gmail.com>
* Guard against dropping constraint that doesn't exist
- Updated wording in migration_helper.php PHPdoc
- Use migration_helper function to drop key which only drops the constraint if it exists.
The core logic was not changed here. It only adds a safety mechanism.
Signed-off-by: objec <objecttothis@gmail.com>
* Remove duplicate call to getResultArray in attribute_links loop
Signed-off-by: objec <objecttothis@gmail.com>
* PSR refactoring
Signed-off-by: objec <objecttothis@gmail.com>
* Remove dead parameter from reassignDuplicateAttributeValues method
The attribute value was not needed and is never used since we have the attribute_ids and those are unique.
Signed-off-by: objec <objecttothis@gmail.com>
* Create potentially missing primary keys before attempting to add constraints.
Signed-off-by: objec <objecttothis@gmail.com>
* Guard datetime creation
Signed-off-by: objec <objecttothis@gmail.com>
* Update regex pattern to handle double-quoted and non-quoted encryption keys
Signed-off-by: objec <objecttothis@gmail.com>
* Issue warning and fallback on unparseable attribute_date during
Signed-off-by: objec <objecttothis@gmail.com>
---------
Signed-off-by: objec <objecttothis@gmail.com>
When searching in the Takings view, entering a plain Sale ID (like '123')
did not return any results. The search only worked with customer names
or with the 'POS 123' format.
The issue was that is_valid_receipt() only recognized 'POS ####' format
or invoice numbers, so plain numeric Sale IDs fell through to the
customer name search branch which doesn't search sale_id.
This fix adds sale_id to the search conditions when the search term is
numeric (ctype_digit check), allowing direct Sale ID searches.
Fixes#4567
Co-authored-by: Ollama <ollama@steganos.dev>
* Add fallback for allowedHostnames environment variable
- In some cases allowedHostnames is set in env but not loaded at the time of check, yet available in other sources. This adds fallback checks.
- Add UnitTest
Signed-off-by: objec <objecttothis@gmail.com>
* Improve the fallback logic for allowedHostnames environment variable
Signed-off-by: objec <objecttothis@gmail.com>
---------
Signed-off-by: objec <objecttothis@gmail.com>
basename() returns string and database column values are strings,
but get_latest_migration() and get_current_version() declare int
return types. PHP 8.0+ enforces strict return types and no longer
silently coerces strings to int, causing a TypeError on fresh
installs.
Fixes#4559
Co-authored-by: Ollama <ollama@steganos.dev>
* Fix is_valid_receipt method bug
Strings submitted with a trailing space and no number caused an unhandled exception because Sale::exists() expects an int but a string was passed to it.
- Add guards
- Minor PSR refactor
Signed-off-by: objec <objecttothis@gmail.com>
* Address review comments
Signed-off-by: objec <objecttothis@gmail.com>
---------
Signed-off-by: objec <objecttothis@gmail.com>
* Bugfixes to get Migration working on MySQL
Signed-off-by: objec <objecttothis@gmail.com>
* MariaDB compatibility fixes
- Drop foreign key constraints before making charset changes
- Fix dropAllForeignKeyConstraints helper function.
- Added `IF EXISTS` to DROP statements
- Do not try to readd FK constraints for tables which were dropped.
- MariaDB 11.8.x changes the default implicit collation to uca1400 which breaks the IndiaGST migration, et. al. Explicitly declare utf8_general_ci in affected migrations.
Signed-off-by: objec <objecttothis@gmail.com>
* Fix changes which break MySQL migrations
- MySQL does not support IF EXISTS in foreign key constraints. Since the PHP is now handling dropping those constraints, these lines are redundant. Remove them.
Signed-off-by: objec <objecttothis@gmail.com>
* Resolve code review recommendations
- Add try/catch around DB connect statement
- Heed result of execute_script function and throw an exception on failure.
Signed-off-by: objec <objecttothis@gmail.com>
* Refactor out duplicate code
Signed-off-by: objec <objecttothis@gmail.com>
* Initialize array variable causing potential issues
Signed-off-by: objec <objecttothis@gmail.com>
---------
Signed-off-by: objec <objecttothis@gmail.com>
* fix: capture CSV import failures in save_tax_data and save_inventory_quantities
- Change save_tax_data() return type from void to bool
- Change save_inventory_quantities() return type from void to bool
- Accumulate failure status with &= operator in save_inventory_quantities
- Update postImportCsvFile() to capture return values and set isFailedRow
- Properly propagate failures to failCodes array
Fixes#4475
* fix: Change isset to !empty for items_taxes_data check
- isset was always true since array was initialized
- Use !empty to properly check if there are tax items to save
Address CodeRabbit review feedback
* fix: Capture inventory insert result in save_inventory_quantities
- Combine inventory insert result with success tracking
- Use &= operator to accumulate failures from both operations
- Ensure failures from inventory inserts are propagated
Address CodeRabbit review feedback
---------
Co-authored-by: Ollama <ollama@steganos.dev>
* docs: Update SECURITY.md with disclosure process and advisory template
- Update published advisories table with CVE-2026-41306 and CVE-2026-41307
- Add disclosure process timeline
- Add vulnerability template for researchers
- Explain GitHub advisory creation workflow
- Document security best practices for researchers
This streamlines the vulnerability reporting process by allowing
researchers to create draft advisories directly on GitHub, reducing
triage overhead.
* docs: Update SECURITY.md with CVE process and reporter acknowledgments
- Add CVE request procedure through GitHub
- Document that existing CVEs should be shared in reports
- Clarify no bug bounty program (voluntary triage)
- Add security best practices for researchers
- Thank security researchers for contributions
- Explain vulnerability template format
* docs: Simplify SECURITY.md - remove CVE table, link to GitHub advisories
---------
Co-authored-by: Ollama <ollama@steganos.dev>
* fix(ci): include hidden files in Docker build context
actions/upload-artifact@v4 excludes hidden files (dotfiles) by default,
causing .htaccess files to be missing from the Docker image. Add
include-hidden-files: true to preserve .htaccess in the build artifact.
* fix(docker): correct permissions and add barcode_type default
- Set proper permissions (750) for writable/logs, writable/uploads,
writable/cache, public/uploads, and public/uploads/item_pics
- Set permissions (640) for writable/uploads/importCustomers.csv
- Add barcode_type default value to prevent 'unknown key' error
during initial migration when database is not yet initialized
---------
Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Allow configuring allowed hostnames via ALLOWED_HOSTNAMES environment
variable as an alternative to app.allowedHostnames in .env file. This
is more convenient for Docker/Compose deployments where environment
variables are set directly in compose files.
The ALLOWED_HOSTNAMES variable takes precedence over app.allowedHostnames
if both are set, allowing deployment-specific overrides.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
actions/upload-artifact@v4 excludes hidden files (dotfiles) by default,
causing .htaccess files to be missing from the Docker image. Add
include-hidden-files: true to preserve .htaccess in the build artifact.
Co-authored-by: Ollama <ollama@steganos.dev>
- updated some files to match the official CodeIgniter 4 skeleton.
- rebuilt package.json from a clean init and modernized metadata and formatting
- rebuilt composer.json with modernized metadata and formatting
- replaced code of conduct text with markdown
- updated Dockerfile to replace deprecated instruction