As far as the application being able to change those fields itself, you can prevent that via column permissions, by leaving out the four audit columns and doing something like:
GRANT INSERT (email, widget_count), UPDATE (email, widget_count) ON TABLE foobar TO PUBLIC;
That way, inserts are guaranteed to use the default values of current_timestamp() and current_user. And a BEFORE UPDATE trigger ensures it changes the other two fields via the trigger function only.
Cheers,
Greg
P.S. Also check out
https://www.pgaudit.org/ (PGAudit) as an alternative approach, which puts the information into your Postgres logs, rather than in the tables themselves.