Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/instructions/update_release_notes.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
applyTo: '**'
---

# Release Notes Update Instructions

## When to Update Release Notes

After completing a code change (bug fix, new feature, enhancement, or breaking change), always ask the user:

**"Would you like me to update the release notes in `docs/explanation/release_notes.md`?"**

## If the User Confirms Yes

Update the release notes file following these guidelines:

### 1. Location
Release notes are located at: `docs/explanation/release_notes.md`

### 2. Version Placement
- Add new entries under the **current version** from `config.py`
- If the version has changed, create a new version section at the TOP of the file
- Format: `### **(vX.XXX.XXX)**`

### 3. Entry Categories

Organize entries under the appropriate category:

#### New Features
```markdown
#### New Features

* **Feature Name**
* Brief description of what the feature does and its benefits.
* Additional details about functionality or configuration.
* (Ref: relevant files, components, or concepts)
```

#### Bug Fixes
```markdown
#### Bug Fixes

* **Fix Name**
* Description of what was broken and how it was fixed.
* Impact or affected areas.
* (Ref: relevant files, functions, or components)
```

#### User Interface Enhancements
```markdown
#### User Interface Enhancements

* **Enhancement Name**
* Description of UI/UX improvements.
* (Ref: relevant templates, CSS, or JavaScript files)
```

#### Breaking Changes
```markdown
#### Breaking Changes

* **Change Name**
* Description of what changed and why.
* **Migration**: Steps users need to take (if any).
```

### 4. Entry Format Guidelines

- **Bold the title** of each entry
- Use bullet points for details
- Include a `(Ref: ...)` line with relevant file names, functions, or concepts
- Keep descriptions concise but informative
- Focus on user-facing impact, not implementation details

### 5. Example Entry

```markdown
* **Custom Logo Display Fix**
* Fixed issue where custom logos uploaded via Admin Settings would only display on the admin page but not on other pages (chat, sidebar, landing page).
* Root cause was overly aggressive sanitization removing logo URLs from public settings.
* (Ref: logo display, settings sanitization, template conditionals)
```

### 6. Checklist Before Updating

- [ ] Confirm the current version in `config.py`
- [ ] Determine the correct category (New Feature, Bug Fix, Enhancement, Breaking Change)
- [ ] Write a clear, user-focused description
- [ ] Include relevant file/component references
- [ ] Place entry under the correct version section
132 changes: 53 additions & 79 deletions application/single_app/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,98 +1,72 @@
# Stage 1: System dependencies and ODBC driver install
ARG PYTHON_MAJOR_VERSION_ARG="3"
ARG PYTHON_MINOR_VERSION_ARG="13"
ARG PYTHON_PATCH_VERSION_ARG="11"
FROM debian:12-slim AS builder
# Create nonroot user/group with a stable UID/GID (choose values consistent with your org)
ARG UID=65532
ARG GID=65532

ARG PYTHON_MAJOR_VERSION_ARG
ARG PYTHON_MINOR_VERSION_ARG
ARG PYTHON_PATCH_VERSION_ARG
FROM mcr.microsoft.com/azurelinux/base/python:3.12 AS builder

ARG UID
ARG GID

# Setup pip.conf if has content
COPY pip.conf.d/ /etc/pip.conf.d

# CA
# copy certs to /etc/pki/ca-trust/source/anchors
COPY custom-ca-certificates/ /etc/ssl/certs
RUN mkdir -p /etc/pki/ca-trust/source/anchors/ \
&& update-ca-trust enable \
&& cp /etc/ssl/certs/*.crt /etc/pki/ca-trust/source/anchors/ \
&& update-ca-trust extract

ENV PYTHONUNBUFFERED=1

RUN set -eux; \
echo "nonroot:x:${GID}:" >> /etc/group; \
echo "nonroot:x:${UID}:${GID}:nonroot:/home/nonroot:/bin/bash" >> /etc/passwd; \
mkdir -p /home/nonroot; \
chown ${UID}:${GID} /home/nonroot; \
mkdir -p /app; \
chown ${UID}:${GID} /app; \
chmod 744 /app

RUN mkdir -p /app/flask_session && chown -R ${UID}:${GID} /app/flask_session
RUN mkdir /sc-temp-files && chown -R ${UID}:${GID} /sc-temp-files

ENV DEBIAN_FRONTEND=noninteractive \
PYTHONIOENCODING=utf-8 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8

# Build deps for CPython and pip stdlib modules
WORKDIR /deps
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
wget ca-certificates \
libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev \
libncursesw5-dev libffi-dev liblzma-dev uuid-dev tk-dev && \
rm -rf /var/lib/apt/lists/*

# Build and install Python from source
# Example: https://www.python.org/ftp/python/3.13.11/Python-3.13.11.tgz
WORKDIR /tmp
RUN wget https://www.python.org/ftp/python/${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG}.${PYTHON_PATCH_VERSION_ARG}/Python-${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG}.${PYTHON_PATCH_VERSION_ARG}.tgz && \
tar -xzf Python-${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG}.${PYTHON_PATCH_VERSION_ARG}.tgz && \
cd Python-${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG}.${PYTHON_PATCH_VERSION_ARG} && \
LDFLAGS="-Wl,-rpath,/usr/local/lib" ./configure --enable-optimizations --enable-shared --with-ensurepip=install --prefix=/usr/local && \
make -j"$(nproc)" && \
make altinstall

USER root
WORKDIR /app
RUN groupadd -g 65532 nonroot && useradd -m -u 65532 -g nonroot nonroot

RUN python${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG} -m venv /app/venv
RUN python${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG} -m pip install wheel
# Copy requirements and install them to system
COPY --chown=${UID}:${GID} application/single_app/requirements.txt .
RUN python3 -m pip install --no-cache-dir -r requirements.txt

# Copy requirements and install them into the virtualenv
ENV PATH="/app/venv/bin:$PATH"
COPY application/single_app/requirements.txt /app/requirements.txt
RUN python${PYTHON_MAJOR_VERSION_ARG}.${PYTHON_MINOR_VERSION_ARG} -m pip install --no-cache-dir -r /app/requirements.txt
FROM mcr.microsoft.com/azurelinux/distroless/python:3.12

# Fix permissions so nonroot can use everything
RUN chown -R 65532:65532 /app
ARG UID
ARG GID

RUN mkdir -p /app/flask_session && chown -R 65532:65532 /app/flask_session
RUN mkdir /sc-temp-files && chown -R 65532:65532 /sc-temp-files
USER 65532:65532
COPY --from=builder /etc/pki /etc/pki
COPY --from=builder /home/nonroot /home/nonroot
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/group /etc/group
COPY --from=builder /usr/lib/python3.12 /usr/lib/python3.12

#Stage 2: Final containter
FROM gcr.io/distroless/base-debian12:latest
ARG PYTHON_MAJOR_VERSION_ARG
ARG PYTHON_MINOR_VERSION_ARG
ARG PYTHON_PATCH_VERSION_ARG
USER ${UID}:${GID}

ENV PYTHONIOENCODING=utf-8 \
COPY --from=builder --chown=${UID}:${GID} /app /app
COPY --from=builder --chown=${UID}:${GID} /sc-temp-files /sc-temp-files

ENV HOME=/home/nonroot \
PATH="/home/nonroot/.local/bin:$PATH" \
PYTHONIOENCODING=utf-8 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
PYTHONUNBUFFERED=1 \
PATH="/app/venv/bin:/usr/local/bin:$PATH" \
LD_LIBRARY_PATH="/usr/local/lib:${LD_LIBRARY_PATH}"
PYTHONUNBUFFERED=1

WORKDIR /app

USER root

# Copy only the built Python interpreter (venv entrypoint handles python/python3)
# Copy the full CPython installation so stdlib modules (e.g., encodings) are available
COPY --from=builder /usr/local/ /usr/local/

# Copy system libraries for x86_64
COPY --from=builder /lib/x86_64-linux-gnu/ \
/lib64/ld-linux-x86-64.so.2 \
/usr/lib/x86_64-linux-gnu/
#/usr/share/ca-certificates \
#/etc/ssl/certs \
#/usr/bin/ffmpeg \
#/usr/share/zoneinfo /usr/share/

# Copy application code and set ownership
COPY --chown=65532:65532 application/single_app/ /app/

# Copy the virtualenv from the builder stage
COPY --from=builder --chown=65532:65532 /app/venv /app/venv
COPY --from=builder --chown=65532:65532 /app/flask_session /app/flask_session
COPY --from=builder --chown=65532:65532 /sc-temp-files /sc-temp-files
COPY --chown=${UID}:${GID} application/single_app ./

# Expose port
EXPOSE 5000

USER 65532:65532


ENTRYPOINT ["/app/venv/bin/python", "-c", "import runpy; runpy.run_path('/app/app.py', run_name='__main__')"]
ENTRYPOINT [ "python3", "/app/app.py" ]
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.237.001"
VERSION = "0.237.003"


SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
Expand Down
9 changes: 9 additions & 0 deletions application/single_app/functions_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,15 @@ def sanitize_settings_for_user(full_settings: dict) -> dict:
else:
sanitized[k] = v

# Add boolean flags for logo/favicon existence so templates can check without exposing base64 data
# These fields are stripped by the base64 filter above, but templates need to know if logos exist
if 'custom_logo_base64' in full_settings:
sanitized['custom_logo_base64'] = bool(full_settings.get('custom_logo_base64'))
if 'custom_logo_dark_base64' in full_settings:
sanitized['custom_logo_dark_base64'] = bool(full_settings.get('custom_logo_dark_base64'))
if 'custom_favicon_base64' in full_settings:
sanitized['custom_favicon_base64'] = bool(full_settings.get('custom_favicon_base64'))

return sanitized

def sanitize_settings_for_logging(full_settings: dict) -> dict:
Expand Down
Binary file modified application/single_app/static/images/custom_logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified application/single_app/static/images/custom_logo_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified application/single_app/static/images/favicon.ico
Binary file not shown.
Loading
Loading