Repository Analysis

postalserver/postal

📮 A fully featured open source mail delivery platform for incoming & outgoing e-mail

5.4 Low AI signal View on GitHub

Analysis Overview

This report presents the forensic synthetic code analysis of postalserver/postal, a Ruby project with 16,671 GitHub stars. SynthScan v2.0 examined 28,533 lines of code across 365 source files, recording 126 pattern matches distributed across 5 syntactic categories. The overall adjusted score of 5.4 places this repository in the Low AI signal band.

The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).

5.4
Adjusted Score
5.4
Raw Score
100%
Time Factor
2026-07-14
Last Push
16.7K
Stars
Ruby
Language
28.5K
Lines of Code
365
Files
126
Pattern Hits
2026-07-14
Scan Date
0.00
HC Hit Rate

What These Metrics Mean

Adjusted Score
Primary synthetic code indicator. Raw score normalised per 1,000 lines of code and multiplied by the temporal discount factor. This is the definitive comparative metric — use it to rank repositories by AI authorship density.
Raw Score
The unmodified sum of all severity-weighted, context-multiplied pattern match scores before temporal discounting. Reflects the absolute signal strength independent of when the repository was last active.
Time Factor
The temporal discount multiplier (0–100%) applied to the raw score. Repositories last updated before ChatGPT's launch (Nov 2022) receive a 5% factor. Full signal is only assigned to repositories active in the post-adoption era (Jan 2024+).
Pattern Hits
Total count of individual pattern matches across all files and categories. A high hit count with a low score may indicate a very large codebase with isolated AI snippets; a low count with a high score indicates dense, concentrated AI signatures.
HC Hit Rate
High+Critical pattern hits per file, averaged across the repository. This orthogonal signal catches repositories where a few files are densely packed with high-severity AI tells — a strong indicator even when the normalised score appears moderate due to codebase size.
Lines of Code / Files
Total lines and files analysed. The scanner examines 94 file extensions. These denominators are used to normalise the score, enabling fair comparison between repositories of vastly different sizes.

Score History

This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.

Severity Breakdown

Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.

CRITICAL 0HIGH 0MEDIUM 12LOW 114

Directory Score Breakdown

This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.

Pattern Findings

The scanner identified 126 distinct pattern matches across 5 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.

Over-Commented Block85 hits · 85 pts
SeverityFileLineSnippetContext
LOW.rubocop.yml21# There should always be empty lines inside a class. For exampleCOMMENT
LOW.rubocop.yml101Lint/BooleanSymbol:COMMENT
LOWapp/models/user_invite.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/organization_user.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/track_domain.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/credential.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/smtp_endpoint.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/ip_address.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/ip_pool_rule.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/address_endpoint.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/http_endpoint.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/webhook_event.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/worker_role.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/organization.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/route.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/queued_message.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/webhook.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/ip_pool.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/webhook_request.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/domain.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/domain.rb21# dkim_error :string(255)COMMENT
LOWapp/models/organization_ip_pool.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/scheduled_task.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/server.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/server.rb21# send_limit :integerCOMMENT
LOWapp/models/user.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/additional_route_endpoint.rb1# frozen_string_literal: trueCOMMENT
LOWapp/models/concerns/has_locking.rb1# frozen_string_literal: trueCOMMENT
LOWapp/senders/smtp_sender.rb161 # Return an array of server hostnames which should receive this messageCOMMENT
LOWapp/lib/worker/process.rb1# frozen_string_literal: trueCOMMENT
LOWapp/controllers/legacy_api/messages_controller.rb1# frozen_string_literal: trueCOMMENT
LOWapp/controllers/legacy_api/base_controller.rb1# frozen_string_literal: trueCOMMENT
LOWapp/controllers/legacy_api/send_controller.rb21 #COMMENT
LOWapp/assets/config/manifest.js1//= link_tree ../imagesCOMMENT
LOWconfig/locales/en.yml1# Files in the config/locales directory are used for internationalizationCOMMENT
LOWconfig/environments/production.rb21 config.public_file_server.enabled = trueCOMMENT
LOWconfig/environments/development.rb41COMMENT
LOWconfig/initializers/application_controller_renderer.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/backtrace_silencers.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/mime_types.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/wrap_parameters.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/assets.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/permissions_policy.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/content_security_policy.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/content_security_policy.rb21# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }COMMENT
LOWconfig/initializers/inflections.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb1# frozen_string_literal: trueCOMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb21# Changing this default means invalidate all encrypted messages generated byCOMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb41# and asynchronous queries will then be enabled.COMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb61# regardless of whether they have a default or not.COMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb81#COMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb101# and you have no plans to rollback.COMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb121#COMMENT
LOWconfig/initializers/new_framework_defaults_7_0.rb141# See https://guides.rubyonrails.org/configuring.html#config-active-support-disable-to-s-conversion for more informationCOMMENT
LOWspec/models/server_spec.rb1# frozen_string_literal: trueCOMMENT
LOWspec/models/server_spec.rb21# send_limit :integerCOMMENT
LOWspec/models/queued_message_spec.rb1# frozen_string_literal: trueCOMMENT
LOWspec/models/organization_spec.rb1# frozen_string_literal: trueCOMMENT
LOWspec/models/domain_spec.rb1# frozen_string_literal: trueCOMMENT
LOWspec/models/domain_spec.rb21# spf_error :string(255)COMMENT
25 more matches not shown…
Self-Referential Comments12 hits · 36 pts
SeverityFileLineSnippetContext
MEDIUMapp/senders/smtp_sender.rb212 # Create a new result objectCOMMENT
MEDIUMapp/lib/smtp_server/server.rb102 # Create a hash to contain a buffer for each client.COMMENT
MEDIUMconfig/initializers/wrap_parameters.rb5# This file contains settings for ActionController::ParamsWrapper whichCOMMENT
MEDIUMconfig/initializers/permissions_policy.rb2# Define an application-wide HTTP permissions policy. For furtherCOMMENT
MEDIUMconfig/initializers/content_security_policy.rb4# Define an application-wide content security policy.COMMENT
MEDIUMlib/postal/signer.rb7 # Create a new SignerCOMMENT
MEDIUMlib/postal/message_db/provisioner.rb55 # Create a new tableCOMMENT
MEDIUMlib/postal/message_db/message.rb351 # Create a new item in the message queue for this messageCOMMENT
MEDIUMlib/postal/message_db/message.rb487 # Create a new linkCOMMENT
MEDIUMlib/postal/message_db/database.rb62 # Create a new message with the given attributes. This won't be saved to the databaseCOMMENT
MEDIUMdb/schema.rb1# This file is auto-generated from the current state of the database. InsteadCOMMENT
MEDIUMdb/schema.rb5# This file is the source Rails uses to define your schema when running `bin/railsCOMMENT
Hyper-Verbose Identifiers22 hits · 24 pts
SeverityFileLineSnippetContext
LOWapp/util/has_prometheus_metrics.rb5 def register_prometheus_counter(name, **kwargs)CODE
LOWapp/util/has_prometheus_metrics.rb10 def register_prometheus_histogram(name, **kwargs)CODE
LOWapp/util/has_prometheus_metrics.rb15 def increment_prometheus_counter(name, labels: {})CODE
LOWapp/util/has_prometheus_metrics.rb22 def observe_prometheus_histogram(name, time, labels: {})CODE
LOWapp/mailers/app_mailer.rb18 def server_send_limit_approaching(server)CODE
LOWapp/mailers/app_mailer.rb23 def server_send_limit_exceeded(server)CODE
LOWapp/models/server.rb223 def authenticated_domain_for_address(address)CODE
LOWapp/models/server.rb251 def find_authenticated_domain_from_headers(headers)CODE
LOWapp/models/concerns/has_authentication.rb29 def authenticate_with_previous_password_first(unencrypted_password)CODE
LOWapp/senders/smtp_sender.rb87 def send_message_to_smtp_client(raw_message, mail_from, rcpt_to, retry_on_connection_error: true)CODE
LOWapp/senders/smtp_sender.rb139 def determine_mail_from_for_message(message)CODE
LOWapp/senders/smtp_sender.rb155 def determine_rcpt_to_for_message(message)CODE
LOWapp/controllers/application_controller.rb50 def redirect_to_with_return_to(url, *args)CODE
LOWapp/helpers/application_helper.rb28 def domain_options_for_select(server, selected_domain = nil, options = {})CODE
LOWapp/helpers/application_helper.rb53 def endpoint_options_for_select(server, selected_value = nil, options = {})CODE
LOWspec/helpers/general_helpers.rb5 def create_plain_text_message(server, text, to = "test@example.com", override_attributes = {})CODE
LOWlib/tracking_middleware.rb61 def dispatch_redirect_request(request, server_token, link_token)CODE
LOWlib/tracking_middleware.rb101 def get_message_db_from_server_token(token)CODE
LOWlib/postal/config_schema.rb604 def substitute_config_file_root(string)CODE
LOWlib/postal/config.rb144 def change_database_connection_pool_size(new_size)CODE
LOWlib/postal/message_db/provisioner.rb114 def remove_raw_tables_older_than(max_age = 30)CODE
LOWlib/postal/message_db/provisioner.rb147 def remove_raw_tables_until_less_than_size(size)CODE
Redundant / Tautological Comments3 hits · 4 pts
SeverityFileLineSnippetContext
LOWapp/lib/smtp_server/server.rb171 # Increment prometheusCOMMENT
LOWconfig/environments/production.rb58 # Set this to true and configure the email server for immediate delivery to raise delivery errors.COMMENT
LOWlib/postal/message_db/message.rb529 # Return the resultCOMMENT
Fake / Example Data4 hits · 4 pts
SeverityFileLineSnippetContext
LOWspec/models/domain_spec.rb210 "admin@example.com",CODE
LOWspec/models/user_spec.rb95 expect(user.name).to eq "John Doe"CODE
LOWspec/factories/organization_factory.rb28 name { "Acme Inc" }CODE
LOWspec/lib/smtp_server/client/data_spec.rb64 expect(client.headers["from"]).to eq ["test@test.com"]CODE